Creating Progressive Web Apps: Build Offline-Capable, Installable Web Apps

Table of Contents
Big thanks to our contributors those make our blogs possible.

Our growing community of contributors bring their unique insights from around the world to power our blog. 

Introduction

Imagine visiting a website that feels as snappy and reliable as a native app—complete with offline access, push notifications, and a home-screen icon—without ever downloading it from an app store. That’s the promise of Progressive Web Apps (PWAs). By combining modern web APIs with thoughtful design, you can deliver an app-like experience straight from the browser. In this guide, we’ll walk you through everything you need to know to create a PWA that works seamlessly offline, installs like a native app, and boosts engagement. Whether you’re a seasoned web developer or just starting out, you’ll learn key concepts, code samples, and best practices to supercharge your next web project.

Understanding Progressive Web Apps

What Is a PWA?

A Progressive Web App is a web application that leverages modern browser capabilities to deliver:

  • Reliability: Loads instantly and works offline or on flaky networks.
  • Speed: Smooth animations and quick responses.
  • Engagement: Can be installed on the home screen and send push notifications.

Analogy: Think of your favorite social media site. Now imagine that, even when you lose signal on the subway, your feed still appears instantly and you can post updates. That’s the offline reliability of a PWA.

Why PWAs Matter

  1. Lower friction: Users skip the app store download and update process.
  2. Cross-platform: Write once, run everywhere—desktop, mobile, tablet.
  3. Improved retention: Home-screen icons keep your brand top of mind.

Core Components of a PWA

1. Web App Manifest

A JSON file that tells the browser how your app should appear when installed.

jsonCopy{
  "name": "My Awesome PWA",
  "short_name": "AwesomePWA",
  "start_url": "/index.html",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#0078d4",
  "icons": [
    {
      "src": "/icons/icon-192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "/icons/icon-512x512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ]
}
  • start_url: Entry point when launched.
  • display: standalone removes browser UI chrome.
  • icons: Used for home-screen and splash.

2. Service Worker

A JavaScript worker that intercepts network requests, manages caching, and enables offline functionality.

javascriptCopy// sw.js
const CACHE_NAME = 'app-cache-v1';
const ASSETS = [
  '/',
  '/index.html',
  '/styles.css',
  '/app.js',
  '/icons/icon-192x192.png'
];

// Install: cache core assets
self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(cache => cache.addAll(ASSETS))
      .then(() => self.skipWaiting())
  );
});

// Fetch: serve cached or fetch from network
self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request)
      .then(cached => cached || fetch(event.request))
  );
});
  • Install event: Pre-caches essential files.
  • Fetch event: Serves from cache first, then network.

Step-by-Step Guide to Building Your PWA

1. Add the Web App Manifest

  1. Create manifest.json in your project root.
  2. Link it in your <head>: htmlCopy<link rel="manifest" href="/manifest.json"> <meta name="theme-color" content="#0078d4">
  3. Provide icons in multiple sizes (192×192, 512×512).

2. Register the Service Worker

Include this in your main JavaScript file:

javascriptCopyif ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/sw.js')
      .then(reg => console.log('SW registered:', reg.scope))
      .catch(err => console.error('SW registration failed:', err));
  });
}

3. Choose a Caching Strategy

  • Cache First: Good for static assets (CSS, JS, icons).
  • Network First: Ideal for frequently updated data (API responses).
  • Stale-While-Revalidate: Serve from cache, then update in background.
javascriptCopy// Example: Network First for API
self.addEventListener('fetch', event => {
  if (event.request.url.includes('/api/')) {
    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))
    );
  }
});

4. Enable Installability

A PWA becomes installable when it meets these criteria:

  1. Served over HTTPS.
  2. Has a valid manifest.
  3. Registers a service worker with a fetch handler.
  4. Contains a <meta name="theme-color">.

Browsers will automatically prompt users with an “Add to Home Screen” banner.

5. Handle Updates Gracefully

javascriptCopyself.addEventListener('activate', event => {
  // Clean up old caches
  event.waitUntil(
    caches.keys().then(keys =>
      Promise.all(keys
        .filter(key => key !== CACHE_NAME)
        .map(key => caches.delete(key))
      )
    )
  );
});

Use self.skipWaiting() and clients.claim() to ensure new service worker takes control immediately.

Advanced PWA Features

Push Notifications

  1. Request permission from users.
  2. Subscribe to a push service.
  3. Listen for push events in your service worker.
javascriptCopyself.addEventListener('push', event => {
  const data = event.data.json();
  event.waitUntil(
    self.registration.showNotification(data.title, {
      body: data.body,
      icon: '/icons/notification.png'
    })
  );
});

Background Sync

Queue actions (e.g., form submissions) and retry when back online:

javascriptCopy// In service worker
self.addEventListener('sync', event => {
  if (event.tag === 'sync-requests') {
    event.waitUntil(processQueue());
  }
});

// In page script
navigator.serviceWorker.ready.then(reg => {
  return reg.sync.register('sync-requests');
});

Testing and Auditing Your PWA

Lighthouse Audits

Use Chrome DevTools → Lighthouse to measure:

  • PWA compliance
  • Performance
  • Accessibility
  • Best practices

Aim for 90+ scores in each category.

Simulate Offline

  • Chrome DevTools: Network → Offline.
  • Firefox Developer Tools: Offline mode toggle.

Verify that core pages load and key functionalities work

Best Practices and Tips

  • HTTPS everywhere: Mandatory for service workers.
  • Minimal initial cache: Cache only what’s needed to launch offline quickly.
  • Responsive design: Ensure your PWA looks good on all screen sizes.
  • Lazy load images: Reduce initial payload.
  • Monitor cache size: Use IndexedDB or Cache Storage Storage API to inspect usage.
  • Graceful error handling: Show user-friendly messages when offline and data is unavailable.

Conclusion

Progressive Web Apps bridge the gap between web and native, delivering fast, reliable experiences that work offline and install on users’ devices. By combining a web app manifest, service worker caching strategies, and best practices like HTTPS and responsive design, you’ll create web applications that delight users and drive engagement. Start small—implement a basic service worker and manifest—and iteratively add features like push notifications or background sync. With these tools and techniques, your next web project can stand out as a true PWA, ready for any network condition.

Let's connect on TikTok

Join our newsletter to stay updated

Sydney Based Software Solutions Professional who is crafting exceptional systems and applications to solve a diverse range of problems for the past 10 years.

Share the Post

Related Posts