- manifest.webmanifest + apple/maskable PNG icons; relative paths so the
app works both at dev root and under /weather
- plain-JS service worker (sw.js) with notificationclick/push handlers and
an SW-mediated showNotification() path for native Android notifications
- src/lib/pwa.js bootstraps registration and routes alerts to the SW
- Every alert kind (storm/precip/heat/cold/uv/wind) is now a per-type
preference toggle in Settings; removed the old alertThresholds.thunderstorm
boolean in favor of notificationTypes.storm
- Store dedups native notifications per forecast day and fires best-effort
native notifications for newly-appeared alerts
- inline-assets keeps manifest/sw/icons in dist; deploy.yml uploads + verifies
all PWA files via WebDAV
The serving layer caches uploaded files, so a plain PUT over the existing
index.html returned 201 but kept serving the old copy, failing the
verify step. Delete first, then PUT (single-line curls: YAML block
scalars don't process backslash continuations).
Build injects __WEATHER_COMMIT__ (VITE_COMMIT_HASH from CI's github.sha on
branch builds, git rev-parse HEAD locally) and main.js logs
console.info({ commit_hash }) so a deploy can be verified to match the
commit that produced it.
Deploys dist/index.html to the WebDAV mirror via basic-auth curl PUT from
WEBDAV_USER/WEBDAV_PASS repo secrets, then verifies the deployed bytes
match the local build. Hard-fails if the secrets are missing so a silent
non-deploy can never look like a success.