Fire tracker for South Africa
# SmokeSignal 🔥
Real-time wildfire detection and alerts, powered by NASA FIRMS satellite data. Fires appear on a clustered Mapbox map with a live fire-danger index, viewport-scoped data loading, and honest staleness reporting (no fire is ever fabricated; fires missing from the latest satellite pass render greyed out).
Languages: English, Afrikaans, isiXhosa.
## Stack
- **Client** — React 18 + TypeScript, Vite, Mapbox GL JS v3 (clustered GL layers), TanStack Query v5 (single shared fires query keyed on a quantized viewport bbox), wouter, Tailwind CSS v3 + a trimmed set of shadcn/ui components, i18next.
- **Server** — Express 4 (single process serves API + client), in-memory fire cache with single-flight FIRMS refresh (every 6 h) persisted to `server/cache/fires-cache.json`, zod-validated endpoints, gzip compression.
- **Shared** — `shared/geo.ts`: bbox/haversine helpers used by both sides (antimeridian-aware).
## Getting started
```bash
npm install
cp .env.example .env # then fill in your keys (optional — see below)
npm run dev
```
Open
localhost. Works on Windows, macOS, and Linux (scripts use `cross-env`; env vars load from `.env` via dotenv).
Without any keys the app still runs: the map is replaced by a list-only dashboard and fire data serves from the last cached FIRMS pull (or an honest 503 when there is none).
### Environment variables
| Variable | Purpose | Get one at |
|---|---|---|
| `FIRMS_API_KEY` | Live VIIRS fire detections (worldwide, 1-day window, fetched 4×/day) |
firms.modaps.eosdis.nasa.gov |
| `MAPBOX_ACCESS_TOKEN` | The map itself |
console.mapbox.com |
| `OPENWEATHER_API_KEY` | Weather blended into the fire-danger index |
home.openweathermap.org |
| `PORT` / `HOST` | Server binding (defaults: 5000; `127.0.0.1` in dev, `0.0.0.0` in production) | — |
### Scripts
| Script | What it does |
|---|---|
| `npm run dev` | Dev server with Vite HMR on port 5000 | …