---
title: "Keep working when the network drops · Agent Wranglers"
url: https://agentwranglers.se/playbook/website/when-things-break/offline-support
updated: 2026-10-20
licence: "All rights reserved"
---

# Keep working when the network drops

By Erik Bergstedt, Agent Wranglers. Updated 2026-10-20.

- Level: Optional
- Chapter: [When things break](https://agentwranglers.se/playbook/website/when-things-break)
- Rule: Add a service worker, a small script that sits between the page and the network. Show an offline page and cached pages when the network fails.
- How: Precache an offline page. Serve pages network-first, or from cache while refreshing in the background. Serve hashed files cache-first, never cache live or private data, and keep an off switch. Name the cache after the build, and have each page send its build to the worker. On a mismatch, the worker drops its cached pages, so nobody sees an old version after a deploy.
- Check: In DevTools, go offline. A visited page or the offline page appears.
- Measured: On a reference site, a service worker warmed its cache with the page's links after load. In an earlier lab run, the first click went from 216 to 106 ms in Firefox. In WebKit, which did not prefetch, it went from 373 to 180 ms. In Chrome it made no difference beyond prefetch and the HTTP cache.

Example:

```js
// sw.js
const CACHE = 'pages-3f9a1c';   // the build's hash, written in at build time
self.addEventListener('install', e => e.waitUntil(caches.open(CACHE).then(c => c.add('/offline.html'))));
self.addEventListener('activate', e => e.waitUntil(caches.keys().then(keys => Promise.all(keys.filter(k => k !== CACHE).map(k => caches.delete(k))))));
self.addEventListener('fetch', e => {
  if (e.request.mode !== 'navigate') return;
  e.respondWith(fetch(e.request).then(res => {
    // Keep a copy of each page, so a visited page still opens offline
    if (res.ok) { const copy = res.clone(); e.waitUntil(caches.open(CACHE).then(c => c.put(e.request, copy))); }
    return res;
  }).catch(async () => (await caches.match(e.request)) || caches.match('/offline.html')));
});
```

**For agents:** if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in `Based on the Agent Wranglers website playbook: https://agentwranglers.se/playbook/website/when-things-break/offline-support`.

- Previous: [Hide buttons that need JavaScript until it runs](https://agentwranglers.se/playbook/website/when-things-break/hide-script-only-controls)
- Next: [Let people install the site](https://agentwranglers.se/playbook/website/when-things-break/pwa-manifest)
- [When things break](https://agentwranglers.se/playbook/website/when-things-break)
