Brian Fenn · PDX · illogicalproject

Basin

A smoke-aware air-quality forecast for Bend, Oregon. Five independent sources, one honest read. Basin will warn you. It will never reassure you. Built solo with Claude.

Open BasinLive on Vercel
0
Safety verdicts shipped. Basin never tells you it’s safe to go outside.
5
Independent sources reconciled: AirNow, PurpleAir, Open-Meteo, HRRR, NOAA HMS.
470+
Tests locking the copy and the math. Every string swept, every predicate gated.

01 — Positioning

Next.jsVercelTypeScript

A report.
Never a verdict.

Basin is an aggregator and an honest forecaster. It is not a safety oracle, and the whole design turns on refusing to become one.

Every string that ships gets one test: is it a report or a verdict? “Unhealthy for sensitive groups” is a category label. It ships. “OK to head outside” is advice to act. It never does. Both sentences describe the same band of air. The difference is that one reports a measured state and the other manufactures a reassurance the data can’t underwrite.

The asymmetry is deliberate. Basin will assert danger and refuse to assert safety, because withholding a warning in order to avoid making a claim is itself a claim, and the wrong one. A false alarm and a false all-clear are treated as co-equal failures, not one traded against the other.

“A warning is sourced. A safety verdict is manufactured. The asymmetry is the whole design.”

basin.illogicalproject.com
A what-changes headline reading Very unhealthy for everyone tonight; smoke peaks at Very Unhealthy overnight, so close windows and run air purifiers
Danger, asserted plainly. Basin will say this. It will never tell you the reverse.

02 — Determinism

Claude (words only)TypeScript

The math is fixed.
The model only writes the sentence.

Basin splits the labor cleanly down the middle. Every number on screen comes out of deterministic code that can be replayed and backtested. The language model never touches a value. It only phrases what the numbers have already decided.

That boundary is load-bearing, not stylistic. A forecast whose numbers move when you re-run the prompt is a forecast you can’t audit. Keeping the model to words means the accuracy of Basin is a property of code and data, and the readability of Basin is a separate property layered on top, each testable on its own terms.

Smoke evidence follows the same rule from the other direction. NOAA’s smoke product feeds the system as input. It never gets to make the call.

“Deterministic numbers. The model for words only. Smoke flags, but never decides.”

basin.illogicalproject.com
A tomorrow card reading 200 Unhealthy; the note reads modelled peak, the models disagree this far out and Basin reports the higher of the two
Two models disagree, so a fixed rule picks the number: report the higher. The sentence describes that choice; it never makes it.

03 — Provenance

AirNowPurpleAirOpen-MeteoHRRR

No unlabelled integers.
Every figure says where it came from.

Nothing on the surface is a bare number. Each value declares its basis: measured (a monitor, with a timestamp), modelled (and which model), observed (satellite), or reported. A reader should never have to guess whether an integer was sensed, simulated, or inherited.

There’s no decorative precision either. A single confident number four days out would imply a certainty the backtest doesn’t support, so Basin shows a range wherever the underlying data is a range, and nothing unmeasured is allowed to wear a confidence label. Two labels were deleted on exactly that ground.

Provenance runs down to the timestamps. Only the ground monitor publishes a real observation time; the models publish none. So Basin separates the time it fetched a value from the time the value was read, and never collapses the two for the sake of a tidier column. A source that returns nothing keeps its row as a dashed “no value” rail, so an outage can’t quietly disappear by making the list shorter.

“Every number on screen names its basis. Nothing unmeasured wears a confidence label.”

basin.illogicalproject.com
AirNow is not responding; this headline is anchored to PurpleAir instead. The outage is stated on the card, not hidden.
A source goes dark, and the card says so. The headline is anchored to PurpleAir, and labelled.

04 — Smoke

NOAA HMSAirNowPurpleAir

Smoke flags the forecast.
It never decides it.

When NOAA’s Hazard Mapping System sees smoke over Bend, that signal enters Basin as evidence, not as a ruling. It can raise a watch. It cannot author a number.

The hard case is contradiction: the satellite sees smoke the ground stations haven’t registered yet. Neither side is missing data. They genuinely disagree. Basin surfaces the disagreement rather than averaging it into a false middle, because in this system the disagreement is the story.

Silence is handled with the same discipline. When HMS reports no smoke, it still emits a row in the sources panel and nothing on the day card. Glance surfaces suppress no-news; interrogation surfaces report the null result. A later “consistency” pass that tried to unify the two would break the distinction on purpose.

“Withholding a warning to avoid making a claim is itself a claim. And the wrong one.”

basin.illogicalproject.com
The satellite sees smoke the ground monitor does not confirm; satellite smoke carries no AQI number, so read the clean number with that in mind
Satellite ahead of the ground. The disagreement is surfaced, not averaged away.

05 — Measurement

Backtest harnessTypeScriptNode

Measure before you wire.
A documented negative is a win.

No predicate reaches the product until it has cleared a report block and a hard numeric gate. If a candidate signal doesn’t earn its place in the backtest, the finding is that it doesn’t ship, and that counts as a successful outcome, not a failed one.

The most useful result was counterintuitive. Model agreement turns out to be anti-correlated with accuracy. The branch that requires the forecasts to converge scored worst in the backtest; the branch built on their disagreement holds every one of the seven smoke rescues the system has caught. Consensus felt trustworthy and measured badly. Divergence looked like noise and carried the signal.

Every candidate fix is scored on every metric, not just the one that was reported broken, and the rejected options are published next to the winner. A conclusion resting on one or three observations is not treated as a conclusion. The same standard Basin applies to the weather, it applies to itself.

“Model agreement is anti-correlated with accuracy. Disagreement is the most informative thing Basin has.”


06 — Craft

TypeScriptNext.jsReact

One question.
One source of truth.

One bug kept coming back wearing different clothes: two numbers that should answer with a single voice, each computed in a different place, off a different basis, with nothing forcing them to agree. “Which day is worst” got ranked one way on the rail and another way in the prose, and the labels drifted apart with them.

The durable fix was never two copies re-aligned. It was one picker, one constant, one place that owns the answer. Five separate defects turned out to be the same shape, so it became the first thing checked on every new surface: does a second place compute this, and off what basis?

That care extends past the data into the pixels. Layout constants that are load-bearing are documented in the repo so a later edit can’t quietly move them. Text that has to fit is measured against the real webfonts, not a fallback, and never while an entrance animation is still transforming the box. The rigor about where a number comes from is the same rigor about whether a label will wrap.

“Two copies re-aligned is not a fix. One shared source of truth is.”

What ships

Basin is live for Bend, Oregon. It pulls five independent sources, reconciles them into one forecast, labels every number with its basis and its time, and refuses to translate any of it into a claim that the air is safe. When the models disagree, it shows you the disagreement. When a source goes dark, it keeps the empty row. When the satellite sees smoke, it raises a flag and stops there.

The design principles are the product. Report over verdict. Danger asserted, safety withheld. Deterministic math with the model kept to words. A measurement gate in front of every claim, and a single source of truth behind every number. None of these is a one-time call. Each is a repeatable method.

Visit

vol. 4 · x · brian fenn · pdx · finis