Build Progressive Web Apps (PWAs) with offline support, installability, and caching strategies. Trigger whenever the user mentions PWA, service workers, web app manifests, Workbox, 'add to home screen', or wants their web app to work offline, feel native, or be installable.
Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.
Quelldateien prüfen
Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Ein direkter Befehl überspringt den Prüf-Prompt. Prüfen Sie die Quelle, bevor Sie ihn ausführen.
Build Progressive Web Apps (PWAs) with offline support, installability, and caching strategies. Trigger whenever the user mentions PWA, service workers, web app manifests, Workbox, 'add to home screen', or wants their web app to work offline, feel native, or be installable.
A Progressive Web App is a web application that uses modern browser capabilities to deliver a fast, reliable, and installable experience — even on unreliable networks. The three required pillars are:
HTTPS — Required in production for service workers to register (localhost is exempt for development).
Web App Manifest (manifest.json) — Makes the app installable and defines its appearance on device home screens.
Service Worker (sw.js) — A background script that intercepts network requests, manages caches, and enables offline functionality.
When to Use This Skill
Use when the user wants their web app to work offline or on unreliable networks.
Use when building a mobile-first web project where users should be able to install the app to their home screen.
Use when the user asks about caching strategies, service workers, or improving web app performance and resilience.
Use when the user mentions Workbox, web app manifests, background sync, or push notifications for the web.
Use when the user asks "can my website be installed like an app?" or "how do I make my site work offline?" — even if they don't use the word PWA.
Deliverables Checklist
Every PWA implementation must include these files at minimum:
index.html — Links manifest, registers service worker
manifest.json — Full app metadata and icon set
sw.js — Service worker with install, activate, and fetch handlers
app.js — Main app logic with SW registration and install prompt handling
offline.html — Fallback page shown when navigation fails offline (required — missing file will cause install to fail)
Step 1: Web App Manifest (manifest.json)
Defines how the app appears when installed. Must be linked from <head> via <link rel="manifest">.
{"name":"My Awesome PWA","short_name":"MyPWA","description":"A fast, offline-capable Progressive Web App.","start_url":"/","scope":"/","display":"standalone","orientation":"portrait-primary","background_color":"#ffffff","theme_color":"#0055ff","icons":[{"src":"/assets/icons/icon-192x192.png","sizes":"192x192","type":"image/png","purpose":"any maskable"},{"src":"/assets/icons/icon-512x512.png","sizes":"512x512","type":"image/png","purpose":"any maskable"}],"screenshots":[{"src":"/assets/screenshots/desktop.png","sizes":"1280x720","type":"image/png","form_factor":"wide"}]}
Key fields:
display: standalone hides browser UI; minimal-ui shows minimal controls; browser is standard tab.
purpose: "maskable" on icons enables adaptive icons on Android (safe zone matters — keep content in center 80%).
screenshots is optional but required for Chrome's enhanced install dialog on desktop.
Step 2: HTML Shell (index.html)
<!DOCTYPE html><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>My Awesome PWA</title><!-- PWA manifest --><linkrel="manifest"href="/manifest.json"><!-- Theme color for browser chrome --><metaname="theme-color"content="#0055ff"><!-- iOS-specific (Safari doesn't fully use manifest) --><metaname="apple-mobile-web-app-capable"content="yes"><metaname="apple-mobile-web-app-status-bar-style"content="default"><metaname="apple-mobile-web-app-title"content="MyPWA"><linkrel="apple-touch-icon"href="/assets/icons/icon-192x192.png"><linkrel="stylesheet"href="/styles.css"></head><body><divid="app"><header><h1>My PWA</h1></header><mainid="content">Loading...</main><!-- Optional: install button, hidden by default --><buttonid="install-btn"hidden>Install App</button></div><scriptsrc="/app.js"></script></body></html>
Step 3: Service Worker Registration & Install Prompt (app.js)
// ─── Service Worker Registration ───────────────────────────────────────────if ('serviceWorker'in navigator) {
window.addEventListener('load', async () => {
try {
const registration = await navigator.serviceWorker.register('/sw.js');
console.log('[App] SW registered, scope:', registration.scope);
} catch (err) {
console.error('[App] SW registration failed:', err);
}
});
}
// ─── Install Prompt (Add to Home Screen) ───────────────────────────────────let deferredPrompt;
const installBtn = document.getElementById('install-btn'); // may be null if omitted// Capture the browser's install prompt — it fires before the browser's own UIwindow.addEventListener('beforeinstallprompt', (e) => {
e.preventDefault(); // Stop automatic mini-infobar on mobile
deferredPrompt = e;
if (installBtn) installBtn.hidden = false; // Show your custom install button
});
if (installBtn) {
installBtn.addEventListener('click', async () => {
if (!deferredPrompt) return;
deferredPrompt.prompt();
const { outcome } = await deferredPrompt.userChoice;
console.log('[App] Install outcome:', outcome);
deferredPrompt = null;
installBtn.hidden = true;
});
}
// Fires when the app is installed (via browser or your button)window.addEventListener('appinstalled', () => {
console.log('[App] PWA installed successfully');
installBtn.hidden = true;
});
Step 4: Service Worker (sw.js)
Cache Versioning (critical — always increment on deploy)
constCACHE_VERSION = 'v1';
constSTATIC_CACHE = `static-${CACHE_VERSION}`;
constDYNAMIC_CACHE = `dynamic-${CACHE_VERSION}`;
// Files to pre-cache during install (the "App Shell")constAPP_SHELL = [
'/',
'/index.html',
'/styles.css',
'/app.js',
'/assets/icons/icon-192x192.png',
'/offline.html', // Fallback page shown when network is unavailable
];
Install — Pre-cache the App Shell
self.addEventListener('install', (event) => {
console.log('[SW] Installing...');
event.waitUntil(
caches.open(STATIC_CACHE).then((cache) => {
console.log('[SW] Pre-caching app shell');
return cache.addAll(APP_SHELL);
})
);
// Activate immediately without waiting for old SW to die
self.skipWaiting();
});
Activate — Clean Up Old Caches
self.addEventListener('activate', (event) => {
console.log('[SW] Activating...');
event.waitUntil(
caches.keys().then((cacheNames) => {
returnPromise.all(
cacheNames
.filter((name) => name !== STATIC_CACHE && name !== DYNAMIC_CACHE)
.map((name) => {
console.log('[SW] Deleting old cache:', name);
return caches.delete(name);
})
);
})
);
// Take control of all pages immediately
self.clients.claim();
});
Safari supports manifests and service workers but does not support beforeinstallprompt — users must install via the Share → "Add to Home Screen" menu manually.
Use the apple-mobile-web-app-* meta tags (shown in index.html above) for proper iOS integration.
Safari may clear service worker caches after ~7 days of inactivity (Intelligent Tracking Prevention).
HTTPS Requirement
Service workers only register on https:// origins. http://localhost is the only exception for development.
Use a tool like mkcert or ngrok if you need HTTPS locally with a custom hostname.
Cache-Busting on Deploy
Always increment CACHE_VERSION in sw.js when deploying new assets. This ensures activate clears old caches and users get fresh files.
A common pattern is to inject the version automatically via your build tool (e.g., Vite, Webpack).
Opaque Responses (cross-origin requests)
Requests to external origins (e.g., CDN fonts, third-party APIs) return "opaque" responses that cannot be inspected. Cache them with caution — a failed opaque response still gets a 200 status.
Prefer staleWhileRevalidate for cross-origin resources, or use a library like Workbox which handles this safely.
Workbox (Optional: Production Shortcut)
For production apps, consider Workbox (Google's PWA library) instead of hand-rolling strategies. It handles edge cases, cache expiry, and versioning automatically.