Hyperlocal rain alert menu bar app
A free, keyless desktop menu bar app that warns about rain at four speeds, states where every number comes from and how certain it is, and learns its own accuracy over time.
Problem
Weather apps give a daily rain percentage for a whole city. Someone who has to bring things in before a shower needs something else: is rain coming to this exact spot, roughly when, and how sure is anyone? Official text warnings cover a whole region, forecast odds keep being quoted after the rain has started, and no free source estimates when rain that is already falling in nearby towns will arrive.
Goal
A free, keyless desktop menu bar tool, readable at a glance, that warns about rain at four distinct speeds, says where every number comes from and how certain it is, never cries wolf, and learns its own accuracy over time.
My role
Sole designer and developer: data-source research, estimation logic, alert policy, desktop integration and tests, plus several rounds of independent AI review whose objections were answered one by one.
Solution
A menu bar plugin in pure standard-library Python. It combines open forecast ensembles, steering winds, official warning areas and advisories, and open satellite infrared imagery into a four-level notice ladder. Each level answers a different question from a different source and is labelled with its certainty.
How it works
Every few minutes the plugin fetches current conditions and forecasts, ensemble runs from three independent forecasting centres, steering winds at two levels, the national weather service's warning areas and thunderstorm advisories, and satellite cloud-top imagery.
Level 1, hours ahead. For each centre, the app counts the share of that centre's runs that put rain on the ground in each three-hour block, and it warns only when at least two of the three centres agree. Pooling all runs together would hand the centre with the most members the deciding vote.
Level 2, the official outlook. The official forecast for the town is relayed as it is.
Level 3, 10 to 60 minutes. This is the original part. Advisories name the towns where rain is falling now inside free-text sentences, so the town list is parsed out of prose, "falling now" is separated from "expected", and names resolve to coordinates from an offline table so the alert path needs no network lookup. A town counts only if it lies upwind inside a cone that narrows with distance; the travel distance is the along-wind component, and the output is an arrival range from a fast and a slow speed factor, never a single minute. Several gates must all pass (falling now, upwind and in range, bulletin fresh, early edge inside the useful window, not already announced), and when one blocks, the menu says which.
Level 4, official warnings. A warning area is resolved to the exact town by a point-in-polygon test and drives an alarm ladder.
Satellite cloud-top temperature and its cooling rate cover storms that form overhead, which upwind logic cannot see. Once it is raining, the app stops quoting odds and says when the rain should end, and it waits for two consecutive dry hours so a lull is not mistaken for the end. Every Level 3 evaluation, including the silent ones, goes to a shadow log with two feedback buttons, and the app refuses to show its own accuracy until it has enough answers to mean something.
Technical challenges
Turning prose bulletins into trustworthy geography.
Avoiding false precision: native three-hour resolution, ensemble agreement that is not a calibrated probability, ranges instead of points, and stale reports discarded.
Redesigning the upwind cone geometry after reviewers rejected a fixed-angle cone.
At-most-once alerting: intent is recorded before dispatch, so a crash loses an alert rather than repeating one, with atomic writes that flush both file and directory, a single-flight lock and a private delivery ledger.
Alert budgets per event and per day, with minimum spacing between alerts.
An alarm that saves the previous volume to disk before raising it and restores it on exit, on a signal or at the next start, verified to survive a hard kill.
Telling a wake-from-sleep network race apart from a real outage.
A menu glyph that changes shape, not only colour, and hazard wording locked in place by tests.
Capabilities
- Four-level rain notice ladder
- Ensemble agreement voting across forecasting centres
- Upwind arrival ranges from free-text advisories
- Official warnings resolved to the exact town
- Overhead storm detection from satellite imagery
- "Rain until" once it is raining
- Best dry window and a seven-day outlook
- Packing advice for other saved places
- Self-calibration log with in-menu feedback
- Stale-data marker and a fallback provider
- Optional push-based hazard alarm relay sharing the same alarm path
Technology
Impact
In daily use, with every alert level verified live end to end, including the approach popup and its feedback capture. A vague daily percentage became timed, sourced and honest notices, and the app is built to replace its assumed speed factors with locally measured ones after a full wet season.
Skills demonstrated
- Applied geospatial reasoning
- Probabilistic thinking and communicating uncertainty
- Parsing semi-structured government data
- Reliable systems design (durability, at-most-once delivery, locking)
- Alert-fatigue design
- macOS integration
- Test-driven development
- Answering adversarial review rigorously
Demo
PlannedA browser replay on a fictional coastline with invented towns and a synthetic stormy afternoon. Fake advisory sentences scroll in, the parser highlights "falling now" against "expected", the narrowing cone and the along-wind distance are drawn over the map, the arrival range updates, and a gate panel shows each gate passing or blocking with its reason. A second panel steps through the four levels and the "rain until" state on synthetic ensemble data; a third shows the shadow log filling from fake feedback until the app is willing to show an accuracy figure. Written fresh, with no real location, feed data or code.
Not built yet. A demo here uses only invented names and data.