// Service worker. // Goal: keep the app usable on flaky/no network without ever serving stale DATA. // • App SHELL (HTML/CSS/JS/manifest) — network-first, fall back to cache so the // app still loads when offline. Successful fetches refresh the cache. // • API (/api/*) — never cached. The client handles offline itself (it queues // check-offs in localStorage and syncs on reconnect). const SW_VERSION = 'v5'; const SHELL_CACHE = 'shell-' + SW_VERSION; const SHELL = [ '/', '/index.html', '/app.js', '/styles.css', '/md.js', '/manifest.webmanifest', '/vendor/motion.global.js' ]; self.addEventListener('install', (event) => { event.waitUntil( // Per-URL (not atomic addAll): one missing/404 entry must not reject the whole batch and // leave the new shell cache empty — otherwise a hard-offline navigation right after a // version bump would fall through to the offline page. allSettled caches what it can. caches.open(SHELL_CACHE) .then((c) => Promise.allSettled(SHELL.map((u) => c.add(u)))) .catch(() => {}) ); self.skipWaiting(); // activate the new worker on next load }); self.addEventListener('activate', (event) => { event.waitUntil((async () => { const keys = await caches.keys(); await Promise.all(keys.filter((k) => k !== SHELL_CACHE).map((k) => caches.delete(k))); await self.clients.claim(); })()); }); const OFFLINE_HTML = '
The checklist needs an internet connection the first time. Try again when you\'re back online.