Session 27: PWA autopilot — NetworkFirst cache policy, stale bucket cleanup, offline fallback, push helper, manifest polish, tier fix (1584 tests)

This commit is contained in:
Kev
2026-06-13 10:57:49 -04:00
parent f8a51cd9d0
commit 66fafd8429
10 changed files with 445 additions and 16 deletions
+68
View File
@@ -4,6 +4,74 @@
2026-06-12
## Current Phase
SHIP BUILD v27.0 — PWA autopilot: deployment-aware service worker, push foundation, offline fallback, install + cookie + tier polish (Session 27)
## Session 27 (2026-06-13) — SHIPPED
Upgraded the PWA from "caches stale content after deploy" to bulletproof.
The service worker stays — it powers push/offline/installs — but its cache
POLICY is now deployment-aware. Much of the foundation already existed
(skipWaiting/clientsClaim, push handlers, InstallPrompt, CookieConsent);
this session fixed the cache strategy and filled the gaps.
Backend 1579 → **1584 tests** (+5), 126 suites, zero regressions. Web build
clean.
### PHASE 1 — SW cache policy (the deploy-staleness fix)
- Replaced `defaultCache` with explicit `runtimeCaching` (Serwist v9
strategy classes): API + navigations + RSC/everything-else are
NetworkFirst (5s timeout) so sports data is never stale; only
content-hashed `/_next/static/` and images/fonts are CacheFirst.
- `skipWaiting`/`clientsClaim` already set — kept.
- Added an `activate` handler that deletes legacy cache buckets (the old
defaultCache set: start-url, next-data, apis, pages-rsc, …), preserving
CURRENT_CACHES + Serwist-managed precache.
### PHASE 2 — Push foundation
- SW `push` + `notificationclick` handlers already existed — kept + added
a `tag`. Created `web/src/lib/pushNotifications.ts`
(subscribeToPush / unsubscribeFromPush / isPushSupported / pushPermission).
Returns null gracefully until NEXT_PUBLIC_VAPID_PUBLIC_KEY exists.
### PHASE 3 — Offline fallback
- Created `web/src/app/offline/page.tsx` (dependency-free client page).
- SW pre-caches `/offline` on install; navigation handler serves it via a
`handlerDidError` plugin when network + cache both miss.
### PHASE 4 — Manifest polish
- `manifest.json`: full name "VYNDR — Sports Prop Intelligence", added
`categories`, explicit icon `purpose`. Kept brand `#06060B` (NOT the
spec's #0A0A0F) for splash/status-bar consistency. Layout already
emits theme-color + apple-mobile-web-app-* via Next metadata API.
### PHASE 5+6 — Install prompt & cookie consent (verified, already done)
- `InstallPrompt` (beforeinstallprompt + iOS hint + 7-day dismissal
cooldown, gated on ≥2 reads) and `CookieConsent` (persists
`vyndr_cookie_consent`, shows once) already implemented and mounted in
layout. No change needed.
### PHASE 7 — Copy
- The literal "NBA · MLB · WNBA" hero badge was already gone (Session 24 →
"EVERY SPORT · EVERY PROP"). Reframed the layout metadata description to
lead with "every sport" (kept per-sport SEO keywords).
### PHASE 8 — Profile tier
- `{profile.tier}` rendered blank when the API returned null/undefined.
Now falls back to 'free' so the tier field is never empty.
### Files created
- `web/src/app/offline/page.tsx`
- `web/src/lib/pushNotifications.ts`
- `tests/unit/pwaManifest.test.js`
### Files modified
- `web/src/sw.ts` (cache strategies + activate cleanup + offline precache)
- `web/public/manifest.json` (name, categories, icon purpose)
- `web/src/app/layout.tsx` (description), `web/src/app/profile/page.tsx` (tier)
---
## Previous Phase
SHIP BUILD v26.0 — Cross-sport tab counts, scan copy, game-card visual polish, empty-section auto-hide (Session 26)
## Session 26 (2026-06-12) — SHIPPED