Live NEXRAD weather radar with NWS alert overlays — bunko.me/radar
- HTML 38.6%
- JavaScript 37.4%
- Python 23.3%
- Dockerfile 0.7%
The loop kept all ~13 frame layers alive (background pre-warm) = ~104 tile <img>s rasterized at the device pixel ratio. On a retina phone the pinch-zoom memory spike exceeded the tab budget and the browser OOM-reloaded the page. Keep only the current + next frame layer live (showFrame prunes the rest); drop the eager 13-layer warm-preload; keepBuffer 1 + updateWhenZooming:false. Mobile load drops from 13 layers/104 tiles to 2 layers/16 tiles and stays flat through zoom and playback. The tile proxy cache keeps the loop smooth despite recreating layers per step. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|---|---|---|
| app | ||
| .gitignore | ||
| docker-compose.yml | ||
| README.md | ||
radar
Live weather radar with NWS warning overlays — bunko.me/radar (public).
A fullscreen Leaflet map over a dark CARTO basemap with:
- Animated radar loop from RainViewer — past frames + nowcast, with a scrubbable timeline, play/pause, speed control, and selectable color schemes.
- IEM NEXRAD composite (Iowa Environmental Mesonet) as a keyless, higher-resolution live-frame alternate (no animation — single composite, updated every 5 min). Shows the scan's valid time + a live countdown to the next scan, and reloads when a new one lands.
- NWS warning polygons from
api.weather.gov— tornado / severe / flash flood warnings and SPC watches for the configured states, color-coded by event, clickable for details, listed in the side rail (click to fly there).
Scoped to a region (default: Oklahoma + surrounding states) — the map fits and is bounded to it, and alerts are filtered to those states.
- Place labels rendered above the radar so city names stay readable, opacity control, geolocation, dBZ legend, and PWA install support.
Architecture
FastAPI backend (app/main.py) that caches the two upstream feeds so the
browser hits a single origin:
GET /api/radar-frames— normalized RainViewerweather-maps.json({host, frames:[{time, path, kind}]}), 60s TTL.GET /api/rvtile/{z}/{x}/{y}?p=&c=— RainViewer tile proxy with a dedup LRU cache + throttled, backoff-on-429 upstream fetches (RainViewer rate-limits direct browser bursts). RainViewer radar is native to ~z7, so the client capsmaxNativeZoom: 7and upscales above that.GET /api/alerts— NWS active alerts forNWS_AREAS, filtered to features with inline polygons, curated properties, 45s TTL, pagination-capped.GET /api/iem-time— latest IEM n0q scan valid time + interval (30s TTL).GET /— the map UI.GET /health,/manifest.webmanifest,/favicon.svg.
Frontend is vanilla JS + Leaflet (app/static/app.js, app/templates/index.html).
Config (env, see docker-compose.yml)
| var | default | meaning |
|---|---|---|
BASE_PATH |
/radar |
path prefix (Caddy strips it) |
DEFAULT_LAT/LON/ZOOM |
Tulsa, z7 | fallback view if no REGION_BOUNDS |
REGION_BOUNDS |
25.5,-109.3,41.2,-88.8 |
S,W,N,E the map fits + is bounded to (OK + neighbors) |
NWS_AREAS |
OK,KS,MO,AR,TX,NM,CO |
states to pull NWS alerts for |
SITE_NAME |
Tulsa, OK |
label in the header |
NWS_USER_AGENT |
— | contact UA required by api.weather.gov |
Deploy
docker compose up -d --build
Routed publicly via the shared Caddy proxy (~/apps/proxy/Caddyfile).
Data sources & credits
RainViewer, Iowa Environmental Mesonet (NEXRAD), NWS / api.weather.gov, CARTO basemaps © OpenStreetMap contributors. Not for life-safety decisions — use official NWS products.