Summary
A new National Alert Browser for iOS that lets users browse active government weather alerts independent of any saved city — by service/country — with a scannable, VoiceOver-first digest. Reached from a new Weather Alerts section in the Browse tab, behind the alertBrowserEnabled feature flag (default on).
Branch: feature/alert-browser · shipped/tested on a physical iPhone throughout.
What it does
Top level — by service/country:
- United States — NWS (
api.weather.gov)
- Canada — Environment Canada / ECCC (
api.weather.gc.ca)
- Europe — MeteoAlarm, 36 member countries (
feeds.meteoalarm.org), each row showing its live active-alert count
The digest (per region):
- Alerts are collapsed by event type so 25 county-level "Flood Warning" products read as one row, not 25.
- Grouped under severity section headers that carry counts ("Severe, 43 alerts").
- Two filters:
- Severity buttons (Extreme / Severe / Moderate / All) — exclusive: each shows only that severity; only "All" is inclusive. Each segment announces its count in VoiceOver ("Extreme, 3 alerts, 1 of 4").
- Type menu (hazard family) — Storms, Tropical, Flooding, Rain, Heat, Winter, Wind, Fire, Fog, Marine & Coastal, Air Quality, Other. Only families present right now are offered, each with a count. "Storms" gathers tornado/thunderstorm/severe-weather products that NWS otherwise scatters across three severities.
- Tapping a category → affected areas → the existing
AlertDetailView.
Architecture: every provider normalizes into the existing WeatherAlert model, so AlertDetailView, severity coloring, and accessibility labels are reused unchanged. New AlertSource cases .eccc / .meteoalarm. No new dependencies.
Key learnings & decisions
- None of the alert sources cost anything. NWS, ECCC, and MeteoAlarm are all free, keyless public services. MeteoAlarm ≠ Open-Meteo — the alert browser makes zero Open-Meteo (paid) calls.
- NWS
/alerts/active rejects a limit param (HTTP 400). It returns all active alerts without pagination. This was the first "Couldn't load alerts" bug.
- NWS severity tags are miscalibrated for browsing: Tornado Warning = Extreme, Severe Thunderstorm Warning = Severe, but the Watches are Moderate and Air Quality is "Unknown." We remap Air Quality → Moderate; the hazard-type filter exists precisely because severity alone doesn't group "storms."
- Small Craft Advisories are tagged Minor (not Moderate), so they only surface under "All" — which let us drop a separate land/marine toggle entirely; the severity buttons handle marine noise for free.
- Feed data quality varies by country. Austria supplies glued English event names ("Heatwarning", "Thunderstormwarning") — we de-glue before "warning". Some feeds emit a raw
awareness_type=3, awareness_level=2 dump instead of an event name — we decode the structured awareness_type code into a real name ("Thunderstorm warning").
- The hazard classifier had to learn two vocabularies. A live sanity check across Canada + 18 European feeds showed 1,334 alerts (35%) landing in "Other" because Europe says "high-temperature" where the US says "heat," issues "rain" warnings, etc. After broadening the keywords and adding a Rain family, "Other" fell to 29 (0.7%) — the only remainder being Greece's genuinely unlabeled "Yellow Warning."
- Accessibility drove the UI. VoiceOver was reading a summary header as one long run-on string; counts were moved onto the severity headers and category rows, and the exclusive severity filter reads its counts per segment.
Design questions still open
- Default severity is "All" (nothing hidden on open) — reduce via buttons. Alternative would be a specific default, but that hides other severities.
- Type menu is a dropdown (11 families won't fit as segments) — could become a second scrollable button row if desired.
- Greece's generic "Yellow Warning" (~28 alerts) stays in "Other."
- Non-European sources beyond CA/US (Australia BOM, Japan JMA, NZ MetService) are candidates but need messier, separate integrations.
- VoiceOver walkthrough of every new screen on-device is still worth a dedicated pass before merge.
Testing
- Builds clean for simulator and device (Xcode 26.6).
- Verified live against all three feeds; cross-checked the digest against raw API counts (e.g. "1 Severe Thunderstorm Warning in the US" matched the feed exactly).
- Hazard classifier validated against live CA + EU data (numbers above).
Summary
A new National Alert Browser for iOS that lets users browse active government weather alerts independent of any saved city — by service/country — with a scannable, VoiceOver-first digest. Reached from a new Weather Alerts section in the Browse tab, behind the
alertBrowserEnabledfeature flag (default on).Branch:
feature/alert-browser· shipped/tested on a physical iPhone throughout.What it does
Top level — by service/country:
api.weather.gov)api.weather.gc.ca)feeds.meteoalarm.org), each row showing its live active-alert countThe digest (per region):
AlertDetailView.Architecture: every provider normalizes into the existing
WeatherAlertmodel, soAlertDetailView, severity coloring, and accessibility labels are reused unchanged. NewAlertSourcecases.eccc/.meteoalarm. No new dependencies.Key learnings & decisions
/alerts/activerejects alimitparam (HTTP 400). It returns all active alerts without pagination. This was the first "Couldn't load alerts" bug.awareness_type=3, awareness_level=2dump instead of an event name — we decode the structuredawareness_typecode into a real name ("Thunderstorm warning").Design questions still open
Testing