1// #155: minimal installability + offline-safe static shell -- NOT full 2// offline data sync (that's a separate, much bigger ask if ever needed, per 3// the issue's stated scope). This exists purely so iOS "Add to Home Screen" 4// registers a real PWA (Safari requires an active service worker for a 5// standalone-display install) and so the static shell (HTML/CSS/JS/icons) 6// still loads if the network drops mid-session -- API calls are always 7// network-only, live data is never served stale from cache. 8 9const CACHE_NAME = "bellcow-shell-v1"; 10const SHELL_ASSETS = [ 11 "/", 12 "/static/index.html", 13 "/static/style.css", 14 "/static/app.js", 15 "/static/cowbell-logo.js", 16 "/static/manifest.json", 17 "/static/img/cowbell-static.svg", 18 "/static/img/cowbell-idle.svg", 19 "/static/icons/icon-192.png", 20 "/static/icons/icon-512.png", 21 "/static/icons/apple-touch-icon.png", 22]; 23 24self.addEventListener("install", (event) => { 25 event.waitUntil( 26 caches.open(CACHE_NAME).then((cache) => cache.addAll(SHELL_ASSETS)).then(() => self.skipWaiting()) 27 ); 28}); 29 30self.addEventListener("activate", (event) => { 31 event.waitUntil( 32 caches 33 .keys() 34 .then((keys) => Promise.all(keys.filter((k) => k !== CACHE_NAME).map((k) => caches.delete(k)))) 35 .then(() => self.clients.claim()) 36 ); 37}); 38 39self.addEventListener("fetch", (event) => { 40 const url = new URL(event.request.url); 41 42 // Anything under /api/ is always live data -- never intercept it, cache 43 // it, or let a stale/offline response stand in for a real one. 44 if (event.request.method !== "GET" || url.pathname.startsWith("/api/")) return; 45 46 // #397: network-first, cache only as an offline fallback. The previous 47 // cache-first strategy served a stale shell immediately on every visit 48 // right after a deploy -- the network fetch there only refreshed the 49 // cache for *next* time, so a normal online visit was permanently one 50 // deploy behind what it actually showed. This still satisfies #155's real 51 // goal (shell still loads if the network drops mid-session) without that 52 // lag on every ordinary visit. 53 event.respondWith( 54 fetch(event.request) 55 .then((res) => { 56 if (res.ok) caches.open(CACHE_NAME).then((cache) => cache.put(event.request, res.clone())); 57 return res; 58 }) 59 .catch(() => caches.match(event.request)) 60 ); 61});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.