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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user