Architecture¶
Backend — FastAPI + DuckDB¶
The backend is a single FastAPI app (dashboard/backend/app/main.py) wired to a read-only DuckDB file via DataEngine. Each page on the frontend maps to one router under app/routers/:
| Page | Router | Responsibility |
|---|---|---|
| Commodities | routers/commodities.py |
TTF gas, EUA CO₂, Coal API2, EUR/USD KPI cards & series |
| Electricity | routers/electricity.py |
DA prices, load/PV/wind overlays, duration curve, heatmap |
| Forecast | routers/forecast.py |
BirdCurve NL DA + ID3 forecasts vs realised |
| ML | routers/ml.py |
Model diagnostics, feature importance, distributions |
| Ancillary | routers/ancillary.py |
aFRR/mFRR capacity & energy |
| Scenarios | routers/scenarios.py |
Long-run capacity & revenue scenarios |
See the API reference for full per-module documentation.
Server-side downsampling¶
Every chart payload runs through LTTB (app/downsampling.py) so the browser never receives more than a few thousand points — extremes (negative-price spikes, ramp events) survive the downsample.
Time handling¶
All timestamps are stored UTC and emitted tz-aware (+00:00 suffix). The data layer uses pd.to_datetime(..., utc=True) everywhere, and the DuckDB connection sets TimeZone='UTC' on connect.
Frontend — React 19 + Vite 7¶
- State / data — TanStack Query, one query per endpoint with
Cache-Control-aware staleness - Charts — ECharts for analytics, TradingView lightweight-charts for time series
- Code-splitting — per-page lazy routes; ECharts in its own vendor chunk
Data layer¶
Single read-only DuckDB file (BIRDCURVE_DUCKDB_PATH), attached by
DataEngine alongside an in-memory sidecars catalog for the optional
EUR/USD and Coal API2 CSVs. Every request runs on its own DuckDB cursor
(the shared connection is not safe for concurrent queries) inside FastAPI's
threadpool, keeping the event loop free during large scans.
DuckDB tables:
ts_15min— 15-minute load, PV, wind, cross-border, imbalance pricests_hourly— hourly DA prices (15-min-aligned rows mixed in from 2025-09-30; consumers filter to:00)ts_4hourly— aFRR/FCR capacity prices and volumes per auction blockts_daily— Gas TTF, CO₂ EUA daily settlesprovenance— per-(table, source) ingestion bookkeeping for/api/data-status
File-based artifacts under BIRDCURVE_MODEL_RESULTS_DIR (not DuckDB tables):
Production_Ensemble_<ts>/— metrics.json, feature list, LightGBM booster,predictions_{training,validation}.csvForecast_<ts>_vNN_<Scenario>/— per-scenario forecast CSV/feather/xlsx files, discovered at startup and re-read per request