# Frontend — React + TypeScript + GeoScene Maps SDK ## Stack - React 18, TypeScript 5, Vite 5 - Tailwind CSS, Recharts, Zustand (state), Axios - `@geoscene/core` (Maps SDK for JavaScript) — POC uses Tianditu basemap + local GeoJSON / FastAPI risk tiles - Playwright (e2e tests) ## Structure ``` frontend/src/ main.tsx # Entry (+ GeoScene theme CSS) App.tsx # Router setup geoscene/ # MapView helpers + layer factories components/ # Reusable UI (maps, charts, nav) legacy/ # Unused former Leaflet map experiments pages/ # Route-level views services/api.ts # Axios client with TTL cache + request dedup stores/ # Zustand stores types/index.ts # Shared TypeScript interfaces utils/ # Helpers (responsive.ts) ``` ## Path Alias `@/` maps to `src/` — use `import { X } from '@/components/X'`. ## Patterns - Components: PascalCase, one per file, default export - Map components: imperative `@geoscene/core` via `createMapView` — do not pass MapView instances between components - Coordinates: GeoScene uses `[longitude, latitude]` - API calls: use `services/api.ts` wrappers (`riskApi`, `alertApi`, `caseApi`, `gridApi`) - State: Zustand stores in `stores/` - Styling: Tailwind utility classes ## Env (optional Enterprise later) See `.env.example` for `VITE_GEOSCENE_PORTAL_URL` / `VITE_LAYER_*`. POC runs without them. ## Running ```bash cd frontend pnpm dev # localhost:3000, proxies /api → localhost:8000 pnpm build # tsc + vite build → dist/ ``` ## Anti-Patterns - Don't call axios directly — use the cached API wrappers in `services/api.ts` - Don't use `any` in TypeScript types — use `unknown` and narrow - Don't mix data fetching with presentation — fetch in pages, render in components - Don't inline styles when Tailwind classes work - Don't create god components (>200 lines) — extract sub-components - Don't reintroduce Leaflet or role/perspective switchers