Skip to content

Feature: Make WeatherMate a PWA (offline mode, installable app, cached API, optional severe-weather alerts) #21

@hoangsonww

Description

@hoangsonww

Summary

Turn WeatherMate into a first-class Progressive Web App so it works offline, is installable on mobile/desktop, loads instantly on repeat visits, and (optionally) delivers severe-weather push alerts for saved locations.

Why

  • Users often check weather with poor connectivity → blank/slow loads today.
  • Installable PWA = native-like experience without app stores.
  • Runtime caching slashes API calls & latency.
  • Opt-in alerts add real value (storms, AQI spikes, rain starting soon).

Scope

1) App Shell + Static Asset Caching

  • Add sw.js and register it on boot.

  • Cache strategy:

    • HTML/CSS/JS/fonts/icons: CacheFirst with versioned precache.
    • Fallback offline page with “Last known weather” for favorites.

2) Runtime Caching for Weather APIs

  • For OpenWeather (and any backend endpoints):

    • Current & forecast: StaleWhileRevalidate, maxAge ~10 min, per-city cache key.
    • AQI: StaleWhileRevalidate, maxAge ~30 min.
    • Network timeout safeguard (e.g., 4s) then serve cache if present.

3) Favorites Offline

  • Persist last successful payload per favorite (IndexedDB).
  • If offline, show “Last updated · ” banner.

4) Installability

  • Verify manifest.json icons, theme, scope; add display_override: ["standalone"].
  • Add “Install WeatherMate” prompt/CTA in the UI when beforeinstallprompt fires.

5) Optional: Severe-Weather Push Alerts (opt-in)

  • UI toggle per favorite: “Notify me about severe alerts for this location.”

  • Backend (tiny Node/Flask service) to:

    • Store Web Push subscriptions.
    • Poll provider alerts (OpenWeather One Call alerts or NWS) on a schedule.
    • Send Web Push via web-push (VAPID).
  • Rate-limit + dedupe alerts; include quick-open deep link.

6) Key Security

  • Do not expose API keys in client. Route through backend proxy or edge function.
  • Add server cache (2–5 min) to reduce upstream usage & costs.

Acceptance Criteria

  • ✅ App passes Lighthouse PWA checks (installable, offline-capable, HTTPS).
  • ✅ Cold boot online < 2s on mid-range mobile (repeat visits near-instant).
  • ✅ Going offline shows cached UI + last known data for favorites.
  • ✅ API runtime caching reduces repeated calls by ≥60% on navigation.
  • ✅ (If enabled) push alerts received for at least one provider with opt-in UX and unsubscribe flow.
  • ✅ Docs added to docs/pwa.md incl. cache invalidation & alert sources.

Implementation Notes

  • Use Workbox for precache + runtime strategies.

    // sw.js (sketch)
    import {precacheAndRoute} from 'workbox-precaching';
    import {registerRoute} from 'workbox-routing';
    import {StaleWhileRevalidate, CacheFirst} from 'workbox-strategies';
    import {ExpirationPlugin} from 'workbox-expiration';
    
    precacheAndRoute(self.__WB_MANIFEST || []);
    
    // Static assets
    registerRoute(({request}) => ['style','script','image','font'].includes(request.destination),
      new CacheFirst({cacheName:'wm-static-v1',
        plugins:[new ExpirationPlugin({maxEntries:100, maxAgeSeconds:30*24*3600})]}));
    
    // Weather API
    registerRoute(({url}) => url.pathname.includes('/weather') || url.pathname.includes('/onecall'),
      new StaleWhileRevalidate({cacheName:'wm-api-v1',
        plugins:[new ExpirationPlugin({maxEntries:300, maxAgeSeconds:10*60})]}));
  • Store per-favorite last payloads in IndexedDB (e.g., idb-keyval).

  • Show an offline banner if navigator.onLine === false.

  • Push: backend stores subscriptions; send via cron or queue; respect quiet hours.

QA / Test Plan

  • Simulate offline in DevTools → favorites render with last data + banner.
  • Throttle network to “Fast 3G” → confirm SW serves shell instantly.
  • Clear caches → first load still works; repeat load < 500ms TTI.
  • Unit tests: cache keying, IndexedDB read/write, install prompt logic.
  • E2E (Playwright): install PWA, reload offline, toggle alerts opt-in/out.

Risks / Mitigations

  • Stale data confusion: Always show “Last updated …” and a manual Refresh.
  • Key exposure: require all weather calls through backend proxy.
  • Push noise: default OFF; allow per-favorite granular control.

Tasks

  • Add service worker + Workbox build step (Vite plugin).
  • Precache manifest, versioning, cache busting.
  • Runtime caching rules (current, forecast, AQI).
  • IndexedDB layer for favorites’ last payloads.
  • Install prompt UX & settings page.
  • Backend /subscribe + Web Push + alert polling (optional).
  • Docs + ENV guidance + API key proxy.
  • Lighthouse budget & CI check.

Metadata

Metadata

Assignees

Labels

documentationImprovements or additions to documentationenhancementNew feature or requestgood first issueGood for newcomershelp wantedExtra attention is neededquestionFurther information is requested

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions