PWA and Service Worker
Cashlytics registers its service worker only in production.
Registration
src/components/pwa/service-worker-registrar.tsx registers /sw.js with scope / in production. In development, it unregisters existing service workers and removes Cashlytics caches to avoid stale local behavior.
Cache Strategy
public/sw.js only handles same-origin GET requests and uses:
- cache-first for
/_next/static/assets - no interception for
/api/*and other/_next/*paths: API responses are never cached - network-first with a per-user offline copy for pages and RSC data, falling back to
/~offline
The offline page is pre-cached during service worker install along with favicon and manifest assets. CACHE_VERSION (currently v2) is part of the cache names; on activate, caches from other versions are deleted.
Per-User Offline Copies
Pages and RSC data are user-specific, so they are stored in a cache named cashlytics-user-<userId>. Only successful, non-redirected responses are stored.
- The app tells the service worker who is signed in with a
SET_USERmessage and clears everything withCLEAR_USERon logout (src/lib/pwa/offline-cache.ts:setOfflineCacheUser,clearOfflineUserData). Switching users deletes the previous user's caches. - Offline, the worker serves that user's copy if it is at most 7 days old (timestamp in the
x-sw-cached-atheader). Otherwise navigations get/~offlineand other requests get a503.
Known gap: every sidebar prefetch (?_rsc=) ends up in the offline cache for 7 days even though it is never used offline.
Push Events
The same service worker handles push and notificationclick. Push payloads can include title, body, icon, badge, and url. Notification clicks focus an existing same-origin app window when possible or open a new one.