Skip to main content
Progressive Web Apps (2026)

Progressive Web Apps in 2026: Offline Support and Push Notifications

Progressive Web Apps promised to close the gap between web and native applications, and in 2026 the promise is partially delivered. Offline support works reliably. Push notifications work on all major platforms including iOS (finally). Installation from the browser produces a genuinely app-like experience on both desktop and mobile. But the gap has not fully closed — background processing, hardware access, and discoverability remain native app advantages. What has changed is that PWAs are now good enough for a large category of applications that previously required native development.

This guide covers the practical implementation of PWA features that matter most — service worker caching strategies, offline support patterns, push notification setup, and installation behaviour across platforms. The focus is on what works reliably in production, not what the specifications promise in theory. The page is part of the web development section and connects to the open web topic hub.


Service worker fundamentals

A service worker is a JavaScript file that the browser runs in the background, separate from your web page. It intercepts network requests and can serve responses from cache, enabling offline support. The lifecycle — registration, installation, activation, and update — determines when cached content changes and how users transition between versions.

// sw.js
const CACHE_NAME = 'v1';
const PRECACHE_URLS = [
'/',
'/offline/',
'/css/main.css',
'/js/app.js',
];

self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME)
.then(cache => cache.addAll(PRECACHE_URLS))
.then(() => self.skipWaiting())
);
});

self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request)
.then(cached => cached || fetch(event.request))
);
});

The basic pattern is straightforward. The complexity lies in choosing the right caching strategy for each type of resource.


Caching strategies that work

Cache-first for static assets. CSS, JavaScript, images, and fonts change infrequently and benefit from being served from cache immediately. Update the cache in the background when a new service worker version activates.

Network-first for HTML pages. Content pages should serve the latest version when the network is available, falling back to cache when offline. This ensures users see current content while maintaining offline access to previously visited pages.

Stale-while-revalidate for API data. Serve cached data immediately for a responsive UI, then update the cache from the network in the background. The next interaction shows fresh data.

// Network-first with cache fallback
self.addEventListener('fetch', (event) => {
if (event.request.mode === 'navigate') {
event.respondWith(
fetch(event.request)
.then(response => {
const clone = response.clone();
caches.open(CACHE_NAME).then(cache => cache.put(event.request, clone));
return response;
})
.catch(() => caches.match(event.request) || caches.match('/offline/'))
);
}
});

Push notifications in 2026

Push notifications on the web work through the Push API and the Notification API, coordinated through a service worker. The user grants permission, your server sends a push message through a push service (Web Push protocol), the service worker receives it and displays a notification.

iOS Safari added Web Push support in version 16.4 (2023), and it has matured through subsequent releases. In 2026, push notifications work on Chrome, Firefox, Edge, Safari (macOS and iOS), and all Chromium-based browsers. The iOS implementation requires the PWA to be added to the home screen — push notifications do not work from the browser tab on iOS.

// Request notification permission
const permission = await Notification.requestPermission();
if (permission === 'granted') {
const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(VAPID_PUBLIC_KEY),
});
// Send subscription to your server
await fetch('/api/push-subscribe', {
method: 'POST',
body: JSON.stringify(subscription),
});
}

Practical note: Push notification permission request timing matters enormously. Requesting permission on page load — before the user has any context — results in high denial rates. Wait until the user takes an action that implies interest in notifications (clicking a "notify me" button, following a topic) and the acceptance rate increases dramatically.


Web app manifest

The manifest file controls how the PWA appears when installed:

{
"name": "My Application",
"short_name": "MyApp",
"start_url": "/",
"display": "standalone",
"theme_color": "#2d3436",
"background_color": "#ffffff",
"icons": [
{ "src": "/icons/192.png", "sizes": "192x192", "type": "image/png" },
{ "src": "/icons/512.png", "sizes": "512x512", "type": "image/png" }
]
}

The GNOME web app icon handling documented elsewhere on this site covers the platform-specific differences in how icons are processed — an important consideration if your PWA targets Linux desktop users alongside mobile.


Installation behaviour across platforms

Chrome (Android and desktop): Shows an install prompt automatically when criteria are met (valid manifest, service worker, served over HTTPS). The beforeinstallprompt event lets you control when to show the prompt.

Safari (iOS): No automatic install prompt. Users must use the "Add to Home Screen" option in the share menu. Your app should guide users to this action with in-app instructions.

Safari (macOS): Supports "Add to Dock" for PWAs in Safari 17+. The installed app runs in its own window without Safari chrome.

Firefox: Removed PWA installation support on desktop. Firefox on Android still supports "Add to Home Screen" but without the full PWA integration that Chromium provides.


What PWAs still cannot do

Background sync is limited — the Background Sync API exists but is restricted to when the browser is open (not true background processing like native apps). Bluetooth and NFC access is available only on Chrome Android. File system access is limited to the Origin Private File System for most browsers.

For applications that need persistent background processing, deep hardware access, or app store distribution, native development or frameworks like Capacitor (which wraps a PWA in a native shell) remain necessary. PWAs are best for applications where the primary interaction happens in the foreground and where the web's reach advantage outweighs the feature limitations.

Field Dispatch

Stay sharp.

New guides and security notes — straight to your inbox when they drop. No noise. No sponsorships. Just the signal.

  • Security & privacy investigations
  • Linux, WSL, and server notes
  • Web performance and dev tooling

Free. No spam. Unsubscribe anytime.