The frontend/ directory contains a React 19 SPA built with Vite 8, TypeScript, TailwindCSS, ECharts, and Leaflet.
cd frontend
npm install
npm run dev # http://localhost:5173
TechGrid + TechCard)Entry point for browsing 55+ technologies. The SideNavBar allows filtering by category (generation, storage, transmission, conversion). The TopNavBar provides a full-text search bar. Results are paginated and displayed in a responsive grid.
TechGrid.tsx — fetches a category’s technologies using React 19 use() inside a <Suspense> boundary; uses useDeferredValue on the search query for non-blocking typing.TechCard.tsx — summary card: name, category badge, OEO URI link, instance count. Click opens DetailsModal.DetailsModal + TechCharts)Full parameter view opened as a modal overlay:
/technologies/{id} deep-link using useOptimistic for instant feedback.TimeSeriesCatalogue + ProfileViewer)Browse and visualise the hourly profile catalogue:
ProfileViewer — an ECharts line chart of the 8 760-step series.UploadProfile — contributor form: upload CSV or JSON with a location picker (MapPickerModal using Leaflet).WorldMapView + TechGeoMap + CountryPanel)Geographic overview of technology instances:
WorldMapView.tsx — zoom-able Leaflet map displaying pins per country where data originates from.TechGeoMap.tsx — clusters technology instances by country; click opens CountryPanel.CountryPanel.tsx — side panel listing all technologies with instances in a selected country, with links to full detail modals.ContributorWorkspace)Authenticated researchers can:
AddTechnology — multi-step form built with InstanceSubForm and visual-builder/.UploadProfile.MapPickerModal (Leaflet map).Submissions enter admin review queue before becoming public.
AdminPanel + ScraperPanel)Guarded by isAdmin flag in AuthContext. Two sub-panels:
AdminPanel.tsx — review pending technology and time-series submissions (approve / reject with notes).ScraperPanel.tsx — display current scraper pipeline status, trigger manual runs, browse scraped candidates, and approve/reject individual parameter extractions for merging into the catalogue.AuthPage + OAuthCallback)Three login methods:
orcid.org; callback stores JWT in sessionStorage.AuthContext.tsx provides the global user, token, and isAdmin state across the entire SPA.
| Mechanism | Used for |
|---|---|
AuthContext (React Context) |
JWT, user identity, isAdmin flag |
| Zustand store | Active category, search query, UI state (modal open/closed) |
React 19 use() + Promise cache |
Async data fetching with Suspense (no loading spinners) |
useDeferredValue |
Non-blocking search input — keeps grid visible while typing |
startTransition |
Smooth category switches without blocking the UI |
useOptimistic |
Instant share-button feedback before async completes |
services/api.ts)The API client is a thin wrapper that:
use() inside <Suspense>, eliminating the need for useEffect/useState data-fetching boilerplate.invalidateCategory() or invalidateAll() after a data mutation.Create frontend/.env.local:
VITE_API_BASE_URL=http://localhost:8000
VITE_SUPABASE_URL=https://<your-project>.supabase.co
VITE_SUPABASE_ANON_KEY=<your-anon-key>
cd frontend
npm run build # TypeScript check + Vite bundle → frontend/dist/
npm run preview # Serve dist/ locally for smoke-testing
Serve frontend/dist/ with any static file server (nginx, Caddy, Vercel, GitHub Pages, Render static site, etc.).
| Library | Version | Role |
|---|---|---|
| React | 19 | UI framework — Server Components pattern, use(), startTransition |
| Vite | 8 | Build tool and dev server (hot-module replacement) |
| TypeScript | 5.9 | Type safety across all components and services |
| TailwindCSS | 3.4 | Utility-first styling (Material Design 3 colour tokens) |
| ECharts | 6.x | Bar charts (CAPEX, efficiency) and line charts (time-series) |
| Leaflet | 1.9 | Interactive world map and location picker |
| Zustand | 5.x | Minimal global state management |
| Supabase JS | 2.x | Auth sessions (email, GitHub, ORCID via JWT) |