Below are all the necessary files and their contents. Place them under your docs/ folder so that MkDocs will copy them into site/ on build.
- docs/sw.js
const CACHE_NAME = 'mkdocs-offline-v1'; const URLS_TO_CACHE = [ '/', '/index.html', '/offline.html', '/css/offline.css', '/manifest.json', '/js/register-sw.js', '/js/update-handler.js', ];
// Install – cache core assets self.addEventListener('install', event => { event.waitUntil( caches.open(CACHE_NAME) .then(cache => cache.addAll(URLS_TO_CACHE)) ); });
// Activate – clean up old caches self.addEventListener('activate', event => { event.waitUntil( caches.keys().then(keys => Promise.all( keys.filter(k => k !== CACHE_NAME) .map(k => caches.delete(k)) ) ) ); });
// Fetch – serve from cache, fall back to network, offline fallback self.addEventListener('fetch', event => { event.respondWith( caches.match(event.request).then(cached => { if (cached) return cached; return fetch(event.request).catch(() => { // If navigation request fails, show offline page if (event.request.mode === 'navigate') { return caches.match('/offline.html'); } }); }) ); });
- docs/js/register-sw.js
if ('serviceWorker' in navigator) { window.addEventListener('load', () => { navigator.serviceWorker .register('/sw.js') .catch(err => console.error('SW registration failed:', err)); }); }
- docs/js/update-handler.js
if ('serviceWorker' in navigator) { navigator.serviceWorker.ready.then(reg => { reg.addEventListener('updatefound', () => { const newWorker = reg.installing; newWorker.addEventListener('statechange', () => { if (newWorker.state === 'installed') { showUpdateNotification(); } }); }); }); }
function showUpdateNotification() { const notice = document.createElement('div'); notice.className = 'offline-notice'; notice.textContent = 'New content available – please refresh.'; document.body.appendChild(notice); notice.style.display = 'block'; }
- docs/css/offline.css
.offline-notice { position: fixed; bottom: 20px; right: 20px; background: #ff9800; color: #fff; padding: 12px; border-radius: 4px; box-shadow: 0 2px 6px rgba(0,0,0,0.2); z-index: 9999; display: none; font-family: sans-serif; }
- docs/offline.html
You’re Offline
Sorry, you need an internet connection to view this page.
- docs/manifest.json
{ "name": "My Docs", "short_name": "Docs", "start_url": "/", "display": "standalone", "background_color": "#ffffff", "theme_color": "#4CAF50", "icons": [ { "src": "assets/images/icon-192.png", "sizes": "192x192", "type": "image/png" } ] }
- mkdocs.yml snippets
Make sure you include these lines so MkDocs will copy your files into the built site:
site_name: My Docs
…¶
extra_javascript: - sw.js - js/register-sw.js - js/update-handler.js
extra_css: - css/offline.css
If you haven’t already, tell MkDocs to include offline.html at root:¶
nav: - Home: index.md - Offline: offline.html
✅ Build & Deploy
mkdocs build mkdocs gh-deploy --clean
Final verification:
Visit https://
In Chrome DevTools → Application → Service Workers → should show your SW as active.
In Network tab (“Offline” checked) → reload → pages in cache still load; others fall back to offline.html.