Skip to main content

Frontend Developer Guide

Technology Stacks

  • React 18 with TypeScript
  • Vite for fast development builds
  • Tailwind CSS + ShadCN UI for components
  • Axios (src/services/api.js) as the centralized HTTP client
  • Lightweight Charts for candlestick and line charts

Project Structure

frontend/
├── src/
│ ├── pages/ # Route-level page components
│ ├── components/ # Reusable UI components
│ ├── services/
│ │ └── api.js # All API calls (Axios instance + method map)
│ ├── hooks/ # Custom React hooks
│ ├── types/ # TypeScript interfaces
│ └── App.tsx # Root component + router
├── public/
├── index.html
├── vite.config.ts
└── package.json

Key Pages

PageFileDescription
BhavDownloadersrc/pages/BhavDownloader.tsxNSE sync + AMI data download
Dashboardsrc/pages/Dashboard.tsxMarket summary
TradeEntrysrc/pages/TradeEntry.tsxTrade journal
OptionChainsrc/pages/OptionChain.tsxF&O chain viewer

Page links live in src/components/Sidebar.jsx, not a top nav bar — it renders only when the logged-in user's rank is DEVELOPER or higher (rankOf(user?.catcode) >= RANK.DEVELOPER, checked in Layout.jsx). A FREE/PAID/POWER/anonymous viewer gets no sidebar at all — just Header.jsx and full-width content. Desktop renders it as a fixed left column; below md it collapses to an off-canvas drawer toggled by a hamburger button in the header.

Asset Allocation is the one exception — it's linked directly from Header.jsx, not the sidebar, because it's the one page visible to every viewer regardless of rank (see User System Design "Public surface in v2.0").

src/constants/rank.js exports the RANK map (ANON..ADMIN) and a rankOf(catcode) helper — mirrors backend/app/auth/deps.py's RANK constant, and is the single copy Sidebar.jsx/Layout.jsx/ProtectedRoute.jsx all import, instead of each keeping its own.

src/components/UserMenu.jsx is the top-right account control: avatar (initial) + email + role badge, click-to-open dropdown with Profile/Sign Out, renders the old "Sign In" button when logged out.

src/components/AdminUserManagement.jsx is ADMIN-only — see teudb Overview "Admin API reference" for the endpoints it drives and where it's mounted.

API Service Pattern

All API calls go through src/services/api.js:

const apiClient = axios.create({
baseURL: import.meta.env.VITE_API_URL || 'http://localhost:8000/api',
});

export const api = {
bhavDownloader: {
triggerDownload: async (date, testingMode) => { ... },
getStatus: async () => { ... },
getAmiFiles: async () => { ... },
}
};

Polling Pattern (BhavDownloader)

Background tasks use a polling loop with a hasSeenRunning guard to prevent premature termination on stale stats.json:

const startPolling = useCallback((alreadyRunning = false) => {
let hasSeenRunning = alreadyRunning;
pollingRef.current = setInterval(async () => {
const res = await api.bhavDownloader.getStatus();
if (res.status === 'RUNNING') {
hasSeenRunning = true;
// Update UI...
} else if (hasSeenRunning) {
// Task completed — stop polling
stopPolling();
}
// If !hasSeenRunning and not RUNNING: task hasn't started writing yet — continue polling silently
}, 1500);
}, []);

Environment Variables

VariableDescription
VITE_API_URLBackend API base URL

Set in .env or .env.local at frontend/.

Running the Frontend

cd frontend
npm install
npm run dev # dev server at http://localhost:5173
npm run build # production build → dist/
npm run preview # preview production build locally