尚未检测到更新。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