Gatsby PWA — Progressive Web App and Offline Support
Learn how to turn your Gatsby site into a Progressive Web App with service workers, manifest, offline support, and install prompts for native-like experience.
In this lesson, you'll configure PWA plugins, set up a web app manifest, implement offline support, and handle service worker updates.
What You'll Learn
How to configure gatsby-plugin-manifest for the web app manifest, gatsby-plugin-offline for service workers, handle offline fallbacks, and manage app updates.
Why It Matters
PWA features improve user engagement: install-to-home-screen, offline access, and faster repeat visits. Gatsby makes PWA implementation straightforward with plugins.
flowchart LR
A[Gatsby Build] --> B[Manifest Plugin]
A --> C[Offline Plugin]
B --> D[manifest.json]
C --> E[Service Worker]
D --> F[Install Prompt]
E --> G[Offline Support]
E --> H[Cache Strategy]
style B fill:#639,color:#fff
style C fill:#4a148c,color:#fff
Web App Manifest
npm install gatsby-plugin-manifest
// gatsby-config.js
module.exports = {
plugins: [
{
resolve: 'gatsby-plugin-manifest',
options: {
name: 'DodaTech Tutorials',
short_name: 'DodaTech',
start_url: '/',
background_color: '#663399',
theme_color: '#663399',
display: 'standalone',
icon: 'src/images/icon.png', // Must be 512x512+
icon_options: {
purpose: 'maskable any'
},
crossOrigin: 'use-credentials'
}
}
]
};
Output: A manifest.json file is generated. When users visit the site, browsers show an "Add to Home Screen" prompt.
Offline Support
npm install gatsby-plugin-offline
// gatsby-config.js — must be listed LAST
module.exports = {
plugins: [
'gatsby-plugin-react-helmet',
'gatsby-plugin-sharp',
'gatsby-plugin-manifest',
'gatsby-plugin-offline' // Always last
]
};
Output: A service worker is generated that caches pages, assets, and data. The site works offline after the first visit.
Offline Fallback Page
Create a custom offline page:
// src/pages/offline.js
import React from 'react';
import { Link } from 'gatsby';
export default function OfflinePage() {
return (
<div style={{ textAlign: 'center', padding: 40 }}>
<h1>You are offline</h1>
<p>Please check your internet connection and try again.</p>
<Link to="/">Try going home</Link>
</div>
);
}
The offline page is displayed when the user navigates to an uncached page while offline.
Service Worker Strategy
Configure caching behavior:
// gatsby-config.js
{
resolve: 'gatsby-plugin-offline',
options: {
precachePages: ['/blog/*', '/about/', '/contact/'],
appendScript: require.resolve('./src/utils/custom-sw.js'),
debug: false,
workboxConfig: {
runtimeCaching: [
{
urlPattern: /^https?:\/\/api\.example\.com\/.*/i,
handler: 'NetworkFirst',
options: {
cacheName: 'api-cache',
expiration: { maxEntries: 50, maxAgeSeconds: 300 }
}
}
]
}
}
}
Output: Specific pages are pre-cached. API responses are cached with a network-first strategy. Custom service worker logic can be appended.
Update Prompt
Notify users when a new version is available:
// src/utils/custom-sw.js
// This script runs in the service worker context
console.log('Custom service worker logic');
// src/components/UpdateNotification.js
import React, { useState, useEffect } from 'react';
export default function UpdateNotification() {
const [hasUpdate, setHasUpdate] = useState(false);
useEffect(() => {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.addEventListener('controllerchange', () => {
setHasUpdate(true);
});
}
}, []);
if (!hasUpdate) return null;
return (
<div style={{
position: 'fixed', bottom: 16, right: 16,
background: '#639', color: '#fff', padding: 16, borderRadius: 8
}}>
<p>A new version is available.</p>
<button onClick={() => window.location.reload()}>Update Now</button>
</div>
);
}
Output: When the service worker detects a new version, a notification appears allowing the user to refresh and get the latest content.
Testing PWA
# Build for production to test PWA
npm run build
# Serve the build locally
npx serve public
Use Lighthouse in Chrome DevToolsk "DevTools" >}} to audit PWA Compliance:
# Expected Lighthouse PWA scores:
# - Installable: Yes (manifest + service worker)
# - Offline support: Yes
# - HTTPS: Required for production
# - Splash screen: Yes
# - Theme color: Yes
Common Mistakes
- Putting
gatsby-plugin-offlinebefore other plugins: It must be LAST in the plugins array. Other plugins register pages before the service worker caches them. - Using a small icon: The manifest icon should be at least 512x512 pixels. Smaller icons cause browser warnings.
- Not serving over HTTPS: Service workers require HTTPS. Use localhost for development, HTTPS for production.
- Forgetting
short_name: Theshort_nameis used on the home screen when there's limited space. It's required for install prompts. - Not testing offline: The service worker caches on first visit. Clear cache, go offline, and verify pages load in incognito mode.
Practice Questions
What is the purpose of
gatsby-plugin-manifest? Answer: It generates amanifest.jsonfile that enables "Add to Home Screen" prompts and controls the PWA appearance.Why must
gatsby-plugin-offlinebe last in the plugins array? Answer: It needs all other plugins to register their pages first so the service worker can cache the complete page list.What happens when a user visits an uncached page offline? Answer: The service worker shows the offline fallback page (if configured) or a browser error.
How do you notify users about app updates? Answer: Listen for
controllerchangeevents on the service worker and show a notification with a refresh button.
Challenge
Configure a full PWA setup with: custom icon design (512x512, 192x192), splash screen colors, offline fallback page with useful content, and an update notification banner.
Mini Project
Turn an existing Gatsby blog into a PWA. Add manifest with all required fields, configure offline support, create a useful offline page with cached recent posts, and add an update notification.
FAQ
What's Next
Learn about Gatsby SSR and DSG for server-side rendering and deferred static generation in Gatsby.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro