name: Pwa Offline First description: Service worker lifecycle, caching strategies, install prompts, offline data sync, IndexedDB patterns, Web App Manifest best practices, and Lighthouse scoring targets. version: 1.0.0
2.2.2 Pwa Offline First
This skill defines the technical standards for building Progressive Web Apps that work reliably regardless of network conditions, install natively on devices, and pass all Lighthouse PWA audits.
1. Web App Manifest (manifest.json)
Goal: Ensure installability and native-like presentation on all platforms.
- Required Fields:
name,short_name,start_url,display(set tostandalone),background_color,theme_color,icons(at minimum 192×192 and 512×512 PNG, includemaskablepurpose variant). - Optional Enhancements:
description,categories,screenshots(for richer install UI on Android),shortcuts(app launcher shortcuts),share_target(to receive shared content). - Scope: Set
scopeto/or the app's root path. Ensurestart_urlfalls within the declared scope. - Validation: Test with Chrome DevTools → Application → Manifest panel. Verify installability criteria are met.
2. Service Worker Lifecycle
Goal: Reliable caching and seamless updates without stale content.
- Registration: Register the service worker in the app's entry point with
navigator.serviceWorker.register('/sw.js', { scope: '/' }). Wrap in a feature check. - Install Event: Pre-cache the App Shell (HTML, CSS, JS, critical fonts, icons) during the
installevent. Usecache.addAll()with a versioned cache name (e.g.,app-shell-v2). - Activate Event: Clean up old caches by iterating
caches.keys()and deleting any cache name that doesn't match the current version. Callclients.claim()to immediately take control. - Update Strategy: Use
skipWaiting()cautiously. Prefer prompting the user with a "New version available — Refresh" banner triggered by thecontrollerchangeevent or a Broadcast Channel message from the new SW.
3. Caching Strategies
Goal: Select the right caching strategy for each resource type.
- Cache First (App Shell): HTML, CSS, JS bundles, fonts, icons. Serve from cache; update cache in background via
fetchand store the new response for the next load. - Network First (API Data): Dynamic content, user data, real-time feeds. Try network; fall back to cached response if offline. Set a network timeout (~3 seconds) before falling back.
- Stale-While-Revalidate (Semi-Static Assets): Images, locale files, non-critical JSON configs. Serve cached version immediately; update cache in background.
- Network Only: Authentication endpoints, payment transactions, real-time WebSocket connections. Never cache sensitive operations.
- Cache Size Management: Implement LRU eviction for dynamic caches. Cap at a reasonable entry count (e.g., 50 API responses, 100 images).
4. Offline Data Persistence (IndexedDB)
Goal: Full offline functionality for data-heavy features.
- Database Design: Use IndexedDB (via
idbwrapper library for Promise-based API) for structured data. Create object stores with appropriate key paths and indexes. - CRUD Operations: Implement complete Create, Read, Update, Delete operations with proper transaction handling (
readwritefor mutations,readonlyfor queries). - Schema Versioning: Use
onupgradeneededto handle database schema migrations. Never delete user data during upgrades — migrate it forward. - Storage Quota: Check available storage with
navigator.storage.estimate(). Request persistent storage withnavigator.storage.persist()if the app holds critical user data.
5. Background Sync & Offline Queue
Goal: Queue user actions taken offline and replay them when connectivity returns.
- Sync Registration: When a network request fails (e.g., form submission, data save), store the request payload in IndexedDB and register a
syncevent withregistration.sync.register('sync-pending-actions'). - Sync Handler: In the service worker's
syncevent listener, read all pending actions from IndexedDB, replay them viafetch(), and delete them from the queue on success. - Fallback: If Background Sync API is not supported, implement a polling-based fallback that checks
navigator.onLineand processes the queue ononlineevents. - Conflict Resolution: For multi-device sync scenarios, implement last-write-wins or timestamp-based merging logic on the backend.
6. Install Prompt Management
Goal: Maximize install rates with strategic prompt timing.
- Capture the Event: Listen for
beforeinstallprompt, prevent default, and store the event reference. Never show the browser's default prompt immediately. - Custom Install UI: Display a custom install banner or button after the user demonstrates engagement (e.g., 2+ sessions, completed a key action). Use the stored event's
.prompt()method when the user clicks. - Post-Install: Listen for
appinstalledevent. Log the conversion. Hide the install prompt permanently. Optionally show a "Welcome to the app!" onboarding flow. - iOS Handling: Detect iOS Safari via user agent. Show manual "Add to Home Screen" instructions since iOS does not support
beforeinstallprompt.
7. Lighthouse PWA Audit Targets
Goal: Every PWA must score 100 on the Lighthouse PWA audit.
- Installable: Valid manifest with required icons, registered service worker, served over HTTPS.
- Reliable: Pages load offline (at least a custom offline fallback page). Response time under 200ms from cache.
- Fast: First Contentful Paint < 1.8s. Largest Contentful Paint < 2.5s. Cumulative Layout Shift < 0.1. Time to Interactive < 3.8s.
- Engagement: Custom splash screen, theme color set, viewport configured, content sized to viewport, no horizontal scroll.
- Testing Cadence: Run Lighthouse in CI on every deploy. Block deploys that drop below target scores.