One page for all VIMS Tidewatch 36-hour storm-tide forecasts: pick any station from a map or list, switch between the 36-hour forecast / last 3 days / last 30 days, toggle MLLW ↔ NAVD88 — no page loads. Every station gets a plain-language flood outlook ("Minor coastal flooding is possible around Tue 7:42 PM…"), NWS flood-stage bands on the chart, a breakdown of how much of the water level is normal tide vs. wind & weather, and severity-colored map dots.
npm install
npm run dev # http://localhost:5173 — dev server proxies VIMS data
npm test # severity-engine unit tests
npm run build # standalone site -> dist/
npm run build:embed # CMS embed bundle -> dist-embed/
npm run stations # regenerate src/data/stations.json (only when the network changes)| What | Where |
|---|---|
| 36 h forecast per station | web4.vims.edu/physical/tidewatch/{CODE}_2018_f36_{MLLW|NAVD}.csv — time,pa30,anom,px30 (UTC, feet, 6-min): astronomic tide, weather surge, total |
| Observations | {CODE}_2018_{3d|30d}_{MLLW|NAVD}.csv — time,feet |
| Station registry | built by scripts/build-stations.mjs from the VIMS ArcGIS station layers, vims.edu station pages, latestobs.csv, NOAA CO-OPS mdapi (datums + flood levels), and USGS NWIS |
Notes discovered while building:
- web4.vims.edu serves no CORS headers. Dev uses a Vite proxy (
/twdata);scripts/serve-embed.mjsshows the ~20-line proxy a deployment needs. The clean long-term fix is asking VIMS IT for oneAccess-Control-Allow-Originheader on/physical/tidewatch/— the data is already public. - NOAA's APIs (flood thresholds, datums) are CORS-open and browser-fetchable.
- Flood thresholds in the VIMS ArcGIS layer are MLLW-relative (verified against NOAA mdapi for Sewells Point). NAVD88 conversions use each station's own dual-datum forecast files, so they work even for non-NOAA gauges.
- Several stations' forecast files are stale (CBBT and Money Point frozen since
June 2022; the old NN*/VB* StormSense sensors since 2019–2025 — the
official site still renders the dead charts). The registry flags current-network
stations as
forecastStale(shown grayed-out, "No current forecast") and drops decommissioned ones.
src/data/severity.ts (pure functions, unit-tested) classifies each station's
forecast window: Normal → Higher than normal → Near flood stage → Minor /
Moderate / Major flooding possible, using NWS flood stages where a station has
them, otherwise VIMS's own "extratidal" concept (water beyond the highest
predicted tide / highest astronomical tide). It emits the headline sentence,
peak height & time (US Eastern), the weather's share of the peak, and the
flood time-window. The same sentence doubles as the chart's screen-reader
description.
Per W&M web guidance (script file + format/block in INCLUDES_EXTRA):
<link rel="stylesheet" href="/path/to/tidewatch.css" />
<div id="tidewatch-dashboard"></div>
<script src="/path/to/tidewatch-dashboard.js"></script>All styles are scoped under .twd-root; the bundle does not touch host-page
globals (verified against a fixture with jQuery 1.12 and hostile CSS:
test/embed-test.html, served by node scripts/serve-embed.mjs). The layout
is container-query responsive, so it adapts to the CMS column it lands in.
Webfonts (Fraunces, Public Sans) are optional; system serif/sans fallbacks
apply if the page doesn't load them.
- The generated outlook sentence is the chart's
aria-label; a "view as a table" toggle renders the full forecast as an hourly HTML table. - Severity is never color-only (text badges everywhere); colors follow NWS conventions and are colorblind-checked.
- All controls are native buttons/inputs, keyboard navigable, with visible
focus rings; the status card is an
aria-liveregion; animations respectprefers-reduced-motion.
This is an unofficial prototype. Forecasts are produced by VIMS; flood stages by NWS/NOAA. Verify against official sources before safety decisions.
