尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證Personal, ad-free, no-login weather PWA: NWS forecasts and observations, radar with HRRR forecast, push alerts
翻譯準備中
取自儲存庫 README
正在載入完整 README。
檢視完整 README ↗Personal, ad-free, no-login weather app. Live at openglades.com/fairweather.
Fairweather blends official National Weather Service forecasts and station observations with high-resolution models, adds a full radar loop with an HRRR forecast, and installs on your phone's home screen as an app with push alerts. Saved places and settings stay in your browser: there are no accounts and no tracking.
Coverage: all 50 states, Puerto Rico, and the U.S. Virgin Islands (wherever the National Weather Service forecasts). Elsewhere it falls back to model-only forecasts, without station readings, alerts, or radar.
Needs Node 20 to 25 (.node-version says 24; better-sqlite3 has no Node 26 build yet).
npm install
cp env.sample .env.local # add a Mapbox public token for the Radar page
npm run dev # http://localhost:3100/fairweather
npm run typecheck
npm run contrast # WCAG contrast check for all 22 palettes
Everything works without a Mapbox token except the Radar map. Push notifications need VAPID keys
(npx web-push generate-vapid-keys); see env.sample.
Fairweather runs as a Node service behind nginx at the /fairweather path, with a crontab for alerts,
rain-soon notifications, and the radar cache. See docs/DEPLOYMENT.md.
app/
layout.tsx, page.tsx root layout (fonts, PWA metadata, theme bootstrap), single page
components/ FairweatherApp shell + Now, Hourly, TenDay, Radar pages, sheets, icons
lib/ client: storage wrapper, themes, formatting, push client, basePath
api/ forecast, alerts, geocode, radar/manifest, radar/tile, push/*, cron/[job]
lib/ server: NWS/Open-Meteo fetchers, forecast merge, radar manifest and tile
cache, MRMS precip type, SQLite, web push, cron jobs; themes.json; types
lib/workers/ mrms-decode.mjs: MRMS GRIB2 decoding off the main thread
public/ sw.js (offline + push), manifest.webmanifest, icons/
scripts/ cron.sh (crontab entry point), contrast.mjs
deploy/ systemd unit and nginx location block
Everything is served under basePath: '/fairweather' (next.config.ts). fetch() calls go through
app/lib/base.ts because Next does not prefix those.
| What | Source | Notes |
|---|---|---|
| Now | Nearest NWS stations (up to 4 within 40 km): best of distance and report age, blended with stations within 25 km reporting at about the same time; used when under 3 h old, else Open-Meteo | Blank API fields are filled from the raw METAR. The forecast nudge only uses readings under 80 min old. When a station says "Clear" but the NWS grid shows 60%+ sky cover (high clouds the sensor can't see), the current-hour NWS condition is used |
| Hourly | Blend: NWS hourly 0.55, NBM 0.25, HRRR 0.15 (moves to NBM after h18), ECMWF 0.05; gusts from the NWS grid | NBM/HRRR/ECMWF come from Open-Meteo's models=. Observation nudge on temp and dew point for hours 0 to 5. Stale grid (over 6 h) drops NWS weight for hours 1 to 12 |
| Days 1 to 7 | NWS forecast periods, verbatim | |
| Days 8 to 10 | Mean of ECMWF, GFS, ICON (whichever reach that day) with spread | If NWS is down, all 10 days are Model and the UI says so |
| Alerts | NWS /alerts/active | |
| AQI | EPA AirNow if AIRNOW_API_KEY, else CAMS via Open-Meteo | |
| Radar, observed | IEM NEXRAD N0Q composite archive (5-min mosaics) | Base reflectivity; one national mosaic covering the lower 48, Alaska, Hawaii, and Puerto Rico |
| Radar, observed precip type | NOAA MRMS PrecipFlag + MergedBaseReflectivityQC from AWS (noaa-mrms-pds), lower 48, Alaska, Hawaii | Rendered to tiles by this server (lib/mrms.ts; GRIB2 template 5.41 decoded in a worker): rain greens to red, snow blues, rain with hail pink |
| Radar, forecast | IEM HRRR tiles (REFD, REFP for precip type), pinned to the newest complete run | Lower 48 only; never mixes runs |
Server responses are cached in memory (forecast 10 min, points 24 h, alerts 2 min).
Radar tiles go through /fairweather/api/radar/tile/..., which stores each tile on disk (data/tiles)
and serves it as immutable. The radar cron job pre-fetches the default 2 h loop and the first 6 h of
forecast around Kansas City and subscribers' saved places, and prunes frames older than 25 h and all
but the newest two HRRR runs. The Radar page adds frames to the map a few at a time, Now first.
Standard Web Push via web-push with VAPID keys from .env.local. The browser's subscription is its
identity and its auth secret is the credential for prefs, unsubscribe, and test sends.
scripts/cron.sh calls POST /fairweather/api/cron/{job} with FAIRWEATHER_CRON_SECRET; nginx
blocks that path from outside.
minutely_15 for the primary (first) location,
3 h cooldown, plus the morning brief once per local day.OBS_STEP_MIN / FCST_STEP_MIN in lib/radarFrames.ts.minutely_15 rather than a radar nowcast.onAccent color was changed to a dark ink.Forecasts, observations, and alerts from NOAA / National Weather Service. Model data (NOAA HRRR, NBM, and GFS, ECMWF IFS, DWD ICON) and air quality (CAMS) via Open-Meteo. Radar from NOAA NEXRAD and HRRR via the Iowa Environmental Mesonet, and NOAA MRMS from the NOAA Open Data Dissemination program on AWS. Air quality from EPA AirNow when configured. Basemaps by Mapbox and OpenStreetMap contributors.
Model forecasts are guidance, not observations. For life-safety decisions, follow official NWS warnings.
MIT © 2026 John Overton