How it works
COWX is a static site hosted on GitHub Pages. There is no application
server. Weather data is pre-fetched by a GitHub Action about every
45 minutes and written into JSON files under public/data/.
Your browser loads only the location you need. If schedules slip, a watchdog quietly
re-dispatches an update around 90 minutes of staleness, and Discord-alerts
only if live data is still unrecovered past about two hours.
Finding your location
- If you previously viewed or favorited a site, we offer that first (stored only in your browser).
- You can search by city/county name or Colorado ZIP code.
- You can enter a Colorado street address or place and tap Set pin. The address string is sent once to OpenStreetMap Nominatim (Colorado-bounded); COWX stores only lat/lon (and an optional display label) in your browser, not the raw address text.
- The Locate button uses high-accuracy browser Geolocation (permission required). We open the nearest catalog city page for the full forecast, and keep a browser-saved pin of your coordinates to refine nearby cameras, road alerts, and PWS from statewide inventories already on the site. The pin survives refresh and new tabs on this device until you search a city or clear site data. Locating always refreshes the workspace even if you are already on that city.
- If needed, a coarse IP-based location is requested from a public geolocation API in your browser, then snapped to the nearest Colorado catalog site. Choosing “Go to” also sets a coarse saved pin. Out-of-state visitors still get the nearest CO site.
- With a pin set, the browser may make one keyless Open-Meteo “current” request for an “At your location” strip (temp/wind at your coordinates). Full 48-hour and 10-day tables stay on the catalog city page. That call is skipped if the network fails.
Data pipeline
The pnpm fetch:data orchestrator calls independent adapters (Open-Meteo
forecast and air quality, Open-Meteo ERA5 climatology refreshed about monthly for
forecast-vs-typical comparisons, NWS alerts/AFD/HWO/FWF, CoAgMET, Aviation Weather
METAR/TAF, USGS gauges, SNOTEL, CDOT cameras plus keyed COtrip incidents/RWIS/road
conditions, CWOP/APRS neighborhood PWS, NOAA HMS smoke, SPC fire weather outlooks, NIFC
nearby wildfire locations, NASA FIRMS satellite fire detections (when keyed), CBRFC
water-supply guidance, Colorado burn-restriction status/links, CDPHE Colorado Smoke Blog
teaser (Blogspot RSS), CAIC avalanche forecast offsite links for mountain regions, NOAA SWPC
space weather, and AirGradient community sensors plus optional AirNow). Each location
payload also gets locally computed astronomy and nearest-ZIP pollen offsite links (no pollen
API key). Each source can succeed or fail on its own. Results are merged into:
index.json— slim list for search and the maplocations/{slug}.json— full drill-down payloadalerts.geojson— warning polygons when geometry is available-
cdot-cameras.geojson/cdot-alerts.geojson/cwop.geojson/hms-smoke.geojson/spc-firewx.geojson/firms-fires.geojson— roadway, APRS, smoke, fire-weather, and satellite hotspot layers -
space-weather.json— statewide NOAA SWPC snapshot (Kp, SFI, R/S/G, HF cues) -
colo-smoke-outlook.json— statewide CDPHE Colorado Smoke Blog teaser (title, published time, short snippet, link out) co-zips.json— ZIP search table-
meta.json— build time, API call count, and per-source status (ok/partial/error/skipped). The home-page footer Sources banner renders those statuses as chips (hover for full names — e.g. COtrip, Climo).
If a non-critical source fails, the site still publishes. If critical sources all fail, the weather fetch step fails and operators can be notified.
Workspace
Each location opens a dual-pane workspace: an animated RainViewer radar
loop beside an At a Glance hero (plain-English bottom-line headline, now
conditions, AQI, and optional pin “At your location” strip). Below that, a full-width
Short-Term Outlook shows compact next-hours cards and scrubbable 24-hour
meteograms (keyboard-accessible handle with a live readout). A specialty band covers CDOT
cameras, keyed COtrip RWIS pavement/air readings, road conditions, and traveler
incidents/events when nearby (re-ranked from your saved pin when Locate or an address pin
was used), local city webcam links (new tab), nearby PWS and other local observations,
astronomy (computed sunrise/sunset, twilight, moon phase), fire weather (SPC Day 1–2
outlooks, HMS smoke, nearby wildfires, burn-restriction status and verify links), and ham
radio context (NOAA SWPC R/S/G scales, SFI/Kp, Colorado aurora chance, heuristic HF band
cues, and model-derived VHF/UHF ducting). Collapsed deep panels hold expandable 48-hour
hourly and 10-day daily tables (with vs-typical deltas when ERA5 climatology is present), a
Compared to typical section (1991–2020 ERA5 day-of-year means — not
official NCEI normals), air quality & pollen offsite links (nearest ZIP Pollen.com
forecast plus AAAAI NAB map — live pollen indexes are not redistributed here), and a
Live data sources panel listing fetch/observation times. The site footer
Sources banner shows per-adapter status chips from
meta.json (including Climo and COtrip when
those adapters ran). Use Refine location on a locality page to set a new
pin.
NWS alert polygons draw on the locality map. While a locality page is open, the browser also
polls api.weather.gov for Colorado active alerts about every three minutes
(paused when the tab is hidden) so warnings appear without waiting for the next scheduled
fetch. Matching uses your saved pin when one is set, otherwise the catalog location;
build-time alerts.geojson remains the fallback. Links to NOAA radar, CSU CIRA
satellite, and other providers remain under External tools. Citizen, pilot, farmer,
firefighter, and ham radio operator needs shape what we fetch, not which panels you
can open.
Failure notifications
GitHub Actions can post to a Discord webhook configured as the repository secret
NOTIFY_WEBHOOK_URL (secret values are never committed). Alerts fire when:
- The scheduled weather fetch step fails (not install or push races after a successful fetch)
- A gh-pages deploy or GitHub Pages build verification fails on production deploys
-
Live data stays unrecovered past about 120 minutes after the stale-data
watchdog has already tried to self-heal (or live
meta.jsonis unreachable)
These notifications do not open a GitHub Issue.
Ad blockers
Please disable your ad blocker on this site (or allowlist
cowx / this domain). COWX has no ads and no trackers, but many blockers still
intercept geolocation and map-related requests.
- Network “Go to” location uses a third-party IP lookup in the browser. Blockers often treat that as tracking and break nearest-city detection.
- Street-address Set pin and some map/tile loads can also fail or look blank when scripts or domains are filtered.
- GPS Locate and typed city/ZIP search usually still work with a blocker on — use those if you keep the blocker enabled.
Privacy
- No accounts and no COWX backend database.
-
Favorites use
localStoragekeyscowx:favoritesandcowx:lastLocation. A hyperlocal GPS/IP/address pin useslocalStoragekeycowx:hyperlocalPin(lat/lon, optional label, source, timestamp) so it survives refresh and new tabs on this browser. It is cleared when you pick a city from search, or when you clear site data for this origin. Address query text is not kept after geocoding. - No third-party analytics by default.
- Optional network location uses a third-party IP geolocation request in the browser (no tracking cookies). See Ad blockers if that step fails.
-
Street-address Set pin sends the query once to OpenStreetMap Nominatim (OSM data under
ODbL). With Locate, IP “Go to”, or an address pin, coordinates may also leave the browser
for the optional Open-Meteo current-conditions request — there is no COWX backend that
stores your pin; it stays only in your browser’s
localStorage. - API keys for AirNow, COtrip, and FIRMS are used only in GitHub Actions at build time — never in the browser. AirGradient uses a free public feed (no key).
Contributors and agents: see AGENTS.md in the repository for adapter and location contribution rules.