A real-time global intelligence dashboard. The system automatically scrapes geopolitical tension data, stores it in a PostgreSQL database, and renders a self-hosted map using PMTiles on a SvelteKit frontend.
The project runs on a fully decoupled, serverless architecture:
| Layer | Component | Description |
|---|---|---|
| Backend | Go + GitHub Actions | Parses global intelligence feeds on a cron schedule and updates the database |
| Database | Supabase PostgreSQL | Stores world_tension scores for every country |
| Map Storage | Supabase Storage | Hosts the 50 MB world_z5.pmtiles file in a public bucket |
| Frontend | SvelteKit on Vercel | Connects the map and database in real-time |
The core UI framework. Chosen for its performance, lack of virtual DOM overhead, and straightforward deployment to the edge.
An open-source map rendering engine used to draw vector map boundaries on the HTML canvas.
A single-file tile format. MapLibre reads the map directly from cloud storage via HTTP Range Requests, so no dedicated map server is needed.
Used for real-time data fetching and public file storage.
The dashboard converts a raw tension score (e.g., -5.2 to +8.5) into a color opacity value on the map using this formula:
const intensity = Math.max(0.2, Math.min(Math.abs(tension_score) / 10, 0.8));
How it works:
Math.abs(score) / 10 — Normalizes the raw score to a decimal (e.g., 8.5 → 0.85).Math.min(..., 0.8) — Caps the maximum opacity at 80% so map borders always stay visible.Math.max(0.2, ...) — Sets a minimum opacity of 20% so countries with near-zero scores don't disappear entirely.If something breaks, check these first:
The GeoJSON file stores 3-letter country codes under the property key ISO3166-1-Alpha-3, not ISO_A3. If the frontend shows STATUS: UNKNOWN for all countries, check whether this key has changed in the GeoJSON file.
The world_tension table requires a value in the fips_code column. Inserting a row without one will fail with:
ERROR 23502 — not-null constraint violation
When running go install inside Git Bash on Windows, use Linux-style paths, not PowerShell syntax:
# Correct
~/go/bin/...
# Incorrect
$home\go\bin\...
npm install
Create a .env file in the project root with your Supabase credentials:
const SUPABASE_URL = "your_project_url";
const SUPABASE_ANON_KEY = "your_anon_key";
const PMTILES_URL = "your_supabase_storage_url/world_z5.pmtiles";
npm run dev
The dashboard will be available at http://localhost:5173.