System diagram
Core components
Next.js frontend
Renders the WebGL map, all HUD panels, and polling logic. Runs in the browser at
http://localhost:3000. Proxies every /api/* call through the Next.js server to BACKEND_URL — the browser never exposes port 8000.FastAPI backend
Python service running on port 8000. Manages background schedulers, the AIS WebSocket stream, and a carrier position tracker. Exposes a small REST API consumed exclusively by the frontend proxy.
Data scheduler
An APScheduler
BackgroundScheduler drives two tiers of data refresh. The fast tier runs every 60 seconds; the slow tier runs every 5 minutes. All fetchers within a tier execute in parallel via ThreadPoolExecutor.AIS WebSocket
A persistent WebSocket connection to
aisstream.io streams live AIS vessel positions into an in-memory dictionary. A Node.js proxy process handles the WebSocket protocol; Python reads its stdout.Two-endpoint design
The backend exposes two primary data endpoints, each returning a different slice of the aggregated dataset:| Endpoint | Poll interval | Contents |
|---|---|---|
GET /api/live-data/fast | 15s (steady state) | Flights, ships, satellites, CCTV, GPS jamming — all moving or frequently-changing entities |
GET /api/live-data/slow | 120s (steady state) | News, earthquakes, fires, stocks, weather, frontlines, GDELT, KiwiSDR, data centers — contextual data that changes infrequently |
s, w, n, e query parameters for server-side bounding-box filtering, which narrows the response to features within the current map viewport (with a 20% padding buffer).
On startup the frontend uses an adaptive polling cadence: it retries every 3 seconds until it receives data, then backs off to the 15s/120s steady-state intervals. This means the dashboard populates within seconds of the backend finishing its initial preload.
Request flow
BACKEND_URL environment variable, you can point the frontend at any backend address without rebuilding the Next.js image.
Startup sequence
The FastAPIlifespan handler fires these steps in order before the server begins accepting requests:
- Secrets loading — reads
*_FILEenvironment variables to support Docker Swarm secrets. - Environment validation —
validate_env(strict=True)checks required keys. - AIS stream — loads disk cache (instant vessel population), then opens WebSocket.
- Carrier tracker — starts OSINT-based carrier position updater.
- Scheduler — registers fast/slow/GDELT/CCTV APScheduler jobs.
- Background preload — runs a full
update_all_data()in a daemon thread so port 8000 is available immediately.