Sources & Methodology
The National Weather Service publishes a Surf Zone Forecast for every coastal zone on the East Coast. It is official, life-safety data, shipped as fixed-width ASCII from teletype-era infrastructure, and almost nobody reads it. Shore extracts that text into structured values, keeps the exact source span behind every one, and draws the result on a map. This page documents where each number comes from and what Shore will not claim.
Where every number comes from
Every source is U.S. federal data, from the National Weather Service and the National Data Buoy Center. Forecast coverage is the 12 East Coast offices — GYX, CAR, BOX, OKX, PHI, AKQ, MHX, ILM, CHS, JAX, MLB and MFL — across 73 surf zones. The three extraction sources are deliberately unlike each other: labelled fixed-width text, nested JSON, and bare numbers that mean nothing without their column position. They share one pipeline, one value type and one provenance model, so adding a source is one file and nothing downstream changes.
Surf Zone Forecast (SRF)
Fixed-width ASCII, dot-leader key/valueRip current risk, surf height, thunderstorm potential, water temperature, wind, UV, tides, remarks
Issued about twice a day by each forecast office. The field set and label wording drift between offices.
https://api.weather.gov/products/types/SRFActive alerts (CAP)
Structured JSONOfficial watches, warnings, advisories and statements affecting each zone
Headlines are shown verbatim. An official product always outranks anything Shore computes.
https://api.weather.gov/alerts/activeBuoy observations (NDBC)
Unlabelled positional numeric tableWave height, water temperature and wind speed measured at moored offshore stations
Nothing but column position says what a number means, and MM means missing. These are offshore readings: a buoy is not a beach, so every value is stamped with its station and none of it feeds the risk assessment.
https://www.ndbc.noaa.gov/data/realtime2/41025.txtForecast zone geometry
GeoJSONThe polygon drawn for each of the 73 surf zones
Fetched once, simplified, and committed as a static file. The map has no runtime dependency on this API.
https://api.weather.gov/zones/forecastThe base map is CARTO Positron over OpenStreetMap data. The satellite layer is USGS/USDA orthoimagery — periodic aerial survey, not a live image, and it can be a season or more old.
How a value gets from text to the map
- 1
Fetch. Each office’s latest product is retrieved and stored byte-for-byte. Documents already stored are skipped, so re-running costs nothing.
- 2
Route. Every document is classified before extraction. A deterministic header check decides when it can; Nemotron is consulted only when it cannot. A document is dropped only when both agree it is not extractable, so the model can never discard data on its own.
- 3
Extract twice. A deterministic parser reads the fixed-width fields by column. Nemotron reads the same text independently and must return a verbatim quote for every value it claims.
- 4
Verify the quote. Each Nemotron value is checked against the stored document. A value whose quote is not found in the source is rejected outright, before anything else looks at it.
- 5
Reconcile. Agreement stores the value at high confidence. Only one extractor finding it stores it at medium. Disagreement is not averaged or guessed — the parser wins by default, and the conflict is recorded.
- 6
Adjudicate. For a genuine disagreement, a deterministic pre-check resolves what the format alone can prove. Anything left is shown to Nemotron with the source text, and it decides which reading matches the document — never which is more dangerous.
- 7
Assess. The rule ladder below runs over the stored values. No model participates in this step.
- 8
Serve. The website reads only the database. It never calls Nemotron on a page load.
Every stored value carries the URL of the product it came from, the exact text span that produced it, the character offsets of that span, when the forecast was issued, which extractor read it, and a confidence level. In the detail panel, clicking any value reveals that span and links to the source document. A value that cannot be read is stored as nothing at all and displayed as Data unavailable.
How risk is decided
Risk comes from a worst-of rule ladder, first match wins. It is deliberately not a weighted score: averaging hazards together can numerically downplay a severe one, and a number like 0.78 cannot be audited against the official forecast. Where a zone is split into sub-areas, the worst value in the zone is the one that counts. Every assessment records which rung fired, and that sentence is what the panel shows.
Warning — An official NWS warning is in effect for the zone.
High — Rip current risk is High, or thunderstorm potential is High.
Elevated — An NWS watch, advisory or statement is in effect; or rip risk is Moderate; or thunderstorm potential is Moderate; or surf reaches 5 ft; or the forecast notes a longshore current.
Lower — Rip current risk is stated and low, and no rung above fired.
No data — Rip current risk is not available for this zone. This never renders green.
The vocabulary mirrors the NWS Low / Moderate / High scale so Shore never appears to disagree with the official source. Shore never describes a beach as safe.
What Nemotron does — and what it is never allowed to do
Shore uses NVIDIA Nemotron 3 Super in four places, none of them conversational. There is no chat interface anywhere in this product.
- Router — classifies an arbitrary document by its structure and decides which extractor, if any, should see it.
- Extractor — reads forecast text independently of the parser, including prose remarks that no regular expression can reach.
- Adjudicator — when parser and model disagree, decides which reading matches the source document.
- Coherence auditor — runs offline and flags zones where the assessment, the fired rule, the official headline and the extracted fields contradict each other.
The constraints matter more than the roles. Nemotron never computes risk. Its values are rejected unless the quote it supplies is found verbatim in the stored document. Where it disagrees with the deterministic parser, the parser wins by default. An adjudication that would lower a hazard is refused. The coherence audit only raises a flag; it cannot change a value. And the audit runs offline, so serving a page never calls a model.
What we measured
Four evaluations are committed with the code, each against a deterministic baseline rather than against nothing. Nemotron beat both baselines outright at routing documents, 20 of 20. It caught a semantic contradiction in the coherence audit that no rule we could write would express, while missing two cases a recomputation catches exactly — which is why Shore ships the union of both. On adjudication, most of the gain turned out to be deterministic rather than model-driven.
The most useful result was a failure. Running both extractors over every forecast surfaced four disagreements, and in all four the parser was wrong: a sub-area name long enough to eat its own dot leader left the values unreadable to a dot-counting regular expression. Nemotron read them correctly, reconciliation refused to store the model’s answer because the parser wins ties, and flagged the conflict instead of guessing. That flag is how we found the bug. The parser now reads sub-area values by column; Wilmington went from 116 to 120 values and disagreements went to zero.
Full numbers, baselines and caveats are in eval/FINDINGS.md, including a measurement artifact we disclosed rather than tuned away.
Limits we will not paper over
- Resolution is the forecast zone, not the beach. An NWS surf zone spans tens of kilometres. Shore colours the zone because that is the resolution the data actually has. Drawing anything finer would be invented precision.
- Rip current risk is a forecast, not an observation. It is issued roughly twice a day. It does not track what the water is doing right now.
- A forecast can be stale. Offices issue on their own schedule, and Shore shows the issue time on every zone and warns when a product is old. An old product is still the current official one.
- No lifeguard data. No authoritative national dataset of lifeguard coverage exists. Showing unverified lifeguard status on a drowning-risk map is the most dangerous thing this product could do, so it is not here.
- Missing data stays missing. When a field is absent, Shore shows Data unavailable and the zone renders grey. It is never filled in by inference, and it never renders green.
Data use
Every source Shore reads is public U.S. federal data, in the public domain under 17 U.S.C. §105. No credentials or licences are required to read any of it. Shore uses public federal sources only and contains no LANXESS data of any kind.
Shore was built at SteelHacks XIII, 19–20 September 2026. Source: github.com/dakshshah1405-ux/Shore.