Lightning overlay on the dashboard radar map (#87 Phase A) #119

Merged
claude-bot merged 1 commit from feat/lightning-overlay into main 2026-07-22 02:00:18 +00:00
Contributor

First half of #87, now that a data source exists — a Weather Pulse (AllisonHouse) ENTLN lightning placefile. Authenticated dashboard only.

  • Secret handling: the feed URL carries a subscriber token and is supplied only via LIGHTNING_PLACEFILE_URL (env) — it appears nowhere in the repo; tests use a fake URL, .env.example has the empty key + a secret comment. Already set in the dev .env.
  • services/lightning.py: parse_placefile() reads the GRLevelX TimeRange+Icon cluster pairs (ignoring the header and the Line:/End: range ring; handles quoted hovertext with embedded commas/newlines). fetch_lightning(lat, lon) appends the required ?version=&lat=&lon= params (the feed 500s without them), caches ~60s per rounded coord, and is fully fail-soft (any error → None).
  • GET /api/lightning/strikes?lat=&lon= (require_user): {"enabled":false} when unconfigured, the parsed clusters on success, {"available":false} on failure.
  • Overlay: a Lightning toggle on the radar modal plots clusters as age-colored (≤5/≤15/older) Leaflet circleMarkers, refreshing on pan + every 60s while active. The toggle is rendered disabled when no feed is configured, so the commercial feed is never fetched unsolicited. Our own markers — not AllisonHouse icon sheets.
  • Licensing: authenticated-only. LIGHTNING_ON_PUBLIC_PAGES exists (default false, documented) but Phase A does not render lightning on public pages.

Testing (dev server)

ruff clean; 19 lightning tests; bulk suite 765 passed. Live check against the real feed: the parser returned all 55 clusters the feed contained (raw Icon: count == parsed strike count).

Part of #87 — Phase A (overlay). Proximity alerts (poll job + per-location radius) are Phase B.

🤖 Generated with Claude Code

First half of #87, now that a data source exists — a Weather Pulse (AllisonHouse) ENTLN lightning placefile. **Authenticated dashboard only.** - **Secret handling**: the feed URL carries a subscriber token and is supplied only via `LIGHTNING_PLACEFILE_URL` (env) — it appears nowhere in the repo; tests use a fake URL, `.env.example` has the empty key + a secret comment. Already set in the dev `.env`. - **`services/lightning.py`**: `parse_placefile()` reads the GRLevelX `TimeRange`+`Icon` cluster pairs (ignoring the header and the `Line:`/`End:` range ring; handles quoted hovertext with embedded commas/newlines). `fetch_lightning(lat, lon)` appends the required `?version=&lat=&lon=` params (the feed 500s without them), caches ~60s per rounded coord, and is **fully fail-soft** (any error → None). - **`GET /api/lightning/strikes?lat=&lon=`** (`require_user`): `{"enabled":false}` when unconfigured, the parsed clusters on success, `{"available":false}` on failure. - **Overlay**: a ⚡ Lightning toggle on the radar modal plots clusters as age-colored (`≤5/≤15/older`) Leaflet `circleMarker`s, refreshing on pan + every 60s while active. The toggle is **rendered disabled when no feed is configured**, so the commercial feed is never fetched unsolicited. Our own markers — not AllisonHouse icon sheets. - **Licensing**: authenticated-only. `LIGHTNING_ON_PUBLIC_PAGES` exists (default **false**, documented) but Phase A does not render lightning on public pages. ## Testing (dev server) ruff clean; 19 lightning tests; bulk suite **765 passed**. **Live check against the real feed**: the parser returned all **55** clusters the feed contained (raw `Icon:` count == parsed strike count). Part of #87 — Phase A (overlay). Proximity alerts (poll job + per-location radius) are Phase B. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Add lightning overlay on the dashboard radar map (#87 Phase A)
All checks were successful
CI / test (pull_request) Successful in 5m37s
24bf208053
Sourced from a Weather Pulse (AllisonHouse) ENTLN placefile. Auth-gated; the feed
URL is a secret (subscriber token) supplied only via LIGHTNING_PLACEFILE_URL env —
never committed.

- app/services/lightning.py: parse_placefile() reads the GRLevelX placefile's
  TimeRange+Icon cluster pairs (ignoring the header and the Line:/End: range ring),
  handling quoted hovertext with embedded commas/newlines; fetch_lightning(lat, lon)
  appends the required ?version=&lat=&lon= params, is cached ~60s per rounded coord,
  and is fully fail-soft (any error -> None, never raises).
- GET /api/lightning/strikes?lat=&lon= (require_user): {"enabled":false} when no
  feed configured, else the parsed clusters, or {"available":false} on failure.
- Dashboard radar modal: a  Lightning toggle (rendered disabled when no feed is
  configured, so the commercial feed is never fetched unsolicited) plots clusters as
  age-colored Leaflet circleMarkers, refreshing on pan and every 60s while active.
  Our own markers — not AllisonHouse icon sheets.
- Config: LIGHTNING_PLACEFILE_URL (secret), LIGHTNING_ON_PUBLIC_PAGES (default
  false, reserved for a later public-page opt-in — Phase A is authenticated-only).

Verified on the dev server against the real feed: parser returned all 55 clusters
the feed contained. ruff clean; 19 lightning tests; bulk 765 passed.

Part of #87 (Phase A — overlay). Proximity alerts are Phase B.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
claude-bot deleted branch feat/lightning-overlay 2026-07-22 02:00:19 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
rbrooks/WeatherBot!119
No description provided.