Skip to content

Gatsby PWA — Progressive Web App and Offline Support

DodaTech Updated 2026-06-28 5 min read

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

  1. Putting gatsby-plugin-offline before other plugins: It must be LAST in the plugins array. Other plugins register pages before the service worker caches them.
  2. Using a small icon: The manifest icon should be at least 512x512 pixels. Smaller icons cause browser warnings.
  3. Not serving over HTTPS: Service workers require HTTPS. Use localhost for development, HTTPS for production.
  4. Forgetting short_name: The short_name is used on the home screen when there's limited space. It's required for install prompts.
  5. Not testing offline: The service worker caches on first visit. Clear cache, go offline, and verify pages load in incognito mode.

Practice Questions

  1. What is the purpose of gatsby-plugin-manifest? Answer: It generates a manifest.json file that enables "Add to Home Screen" prompts and controls the PWA appearance.

  2. Why must gatsby-plugin-offline be 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.

  3. 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.

  4. How do you notify users about app updates? Answer: Listen for controllerchange events 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

Can I customize the service worker?

: Yes. Use the appendScript option to inject custom service worker logic, or eject the service worker with gatsby-plugin-offline's eject option.

Does PWA work on iOS?

: Partially. Safari supports manifest and offline caching but with limitations. iOS doesn't support periodic background sync or push notifications.

How do I test PWA locally?

: Run gatsby build && gatsby serve and use Chrome DevTools Application tab. Check the Manifest and Service Worker sections.

Does offline support work for dynamic content?

: The service worker caches pages at build time. For dynamic content, configure runtime caching in workboxConfig.

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