Skip to main content
Progressive Web Apps·Lesson 1 of 5

PWA Concepts

Progressive Web Apps (PWAs) combine the best of web and native applications. They are regular websites that use modern browser APIs to deliver app-like experiences — installable, fast, reliable, and capable of working offline.

What Makes a PWA?

A PWA is not a specific technology. It is a set of patterns and APIs that, together, make a web app feel like a native app.

Core Characteristics

FeatureDescription
InstallableUsers can add it to their home screen
Offline-capableWorks without an internet connection
ResponsiveFits any screen size
LinkableShared via URL, no app store needed
SecureServed over HTTPS
Re-engageablePush notifications bring users back
FreshAlways up-to-date via service worker updates

PWA vs Native Apps vs Traditional Web

CapabilityTraditional WebPWANative App
Works offlineNoYesYes
InstallableNoYesYes
Push notificationsNoYesYes
App store requiredNoNoYes
URL-based sharingYesYesNo
Automatic updatesYesYesNo
Device API accessLimitedGoodFull
Cross-platformYesYesNo

The Three Pillars

Every PWA is built on three core technologies:

1. HTTPS

PWAs require a secure connection. Service workers — the technology that enables offline support — only work over HTTPS (or localhost during development).

2. Web App Manifest

A JSON file that tells the browser about your app — its name, icons, colors, and how it should behave when installed.

{
  "name": "Sabaoon Academy",
  "short_name": "Academy",
  "description": "Learn web development with practical courses",
  "start_url": "/",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#E21B1B",
  "icons": [
    {
      "src": "/icons/icon-192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "/icons/icon-512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ]
}

Link it in your HTML:

<link rel="manifest" href="/manifest.json" />
<meta name="theme-color" content="#E21B1B" />

Display Modes

ModeDescription
fullscreenNo browser UI at all
standaloneLooks like a native app (no address bar)
minimal-uiSmall set of browser controls
browserNormal browser tab

3. Service Worker

A JavaScript file that runs in the background, separate from the web page. It intercepts network requests, caches resources, and enables offline functionality.

// Register a service worker
if ("serviceWorker" in navigator) {
  window.addEventListener("load", async () => {
    try {
      const registration = await navigator.serviceWorker.register("/sw.js");
      console.log("SW registered:", registration.scope);
    } catch (error) {
      console.error("SW registration failed:", error);
    }
  });
}

The Service Worker Lifecycle

Service workers go through a specific lifecycle:

1. Registration

The page tells the browser where the service worker file lives.

2. Installation

The browser downloads and parses the service worker. The install event fires, and this is where you typically cache your app shell.

// sw.js
const CACHE_NAME = "app-v1";
const ASSETS = ["/", "/index.html", "/styles.css", "/app.js"];

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

3. Activation

After installation, the service worker activates. This is where you clean up old caches.

self.addEventListener("activate", (event) => {
  event.waitUntil(
    caches.keys().then((keys) =>
      Promise.all(
        keys
          .filter((key) => key !== CACHE_NAME)
          .map((key) => caches.delete(key))
      )
    )
  );
});

4. Fetch Interception

The activated service worker intercepts all network requests from pages within its scope.

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

PWA Installability

For a PWA to be installable, it needs:

  1. A valid web app manifest with required fields
  2. A registered service worker with a fetch event handler
  3. To be served over HTTPS
  4. An icon at least 192x192 pixels

The Install Prompt

Browsers show an install prompt when these criteria are met. You can also create a custom install button:

let deferredPrompt;

window.addEventListener("beforeinstallprompt", (event) => {
  event.preventDefault();
  deferredPrompt = event;
  showInstallButton();
});

async function handleInstallClick() {
  if (!deferredPrompt) return;

  deferredPrompt.prompt();
  const { outcome } = await deferredPrompt.userChoice;
  console.log(`User ${outcome === "accepted" ? "installed" : "dismissed"} the app`);
  deferredPrompt = null;
}

Auditing with Lighthouse

Google's Lighthouse tool audits your PWA against best practices:

# Run from Chrome DevTools  Lighthouse tab
# Or via CLI:
npx lighthouse https://your-site.com --view

Lighthouse checks:

  • Service worker registration
  • HTTPS usage
  • Web app manifest validity
  • Offline capability
  • Performance metrics
  • Accessibility

App Shell Architecture

The app shell is the minimal HTML, CSS, and JavaScript needed to render the UI. Cache it during install so the app loads instantly, even offline.

App Shell (cached):
├── index.html       (layout, navigation)
├── styles.css       (all styles)
├── app.js           (core JavaScript)
└── icons/           (app icons)

Dynamic Content (fetched from network):
├── /api/posts       (blog posts)
├── /api/courses     (course data)
└── /api/user        (user profile)

The shell loads from cache immediately, then dynamic content loads from the network (or from cache if offline).

Practical Exercise

Create a minimal PWA setup:

<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scal=1.0" />
  <meta name="theme-color" content="#E21B1B" />
  <link rel="manifest" href="/manifest.json" />
  <title>My PWA</title>
</head>
<body>
  <h1>My Progressive Web App</h1>
  <p id="status">Checking connection...</p>

  <script>
    // Register service worker
    if ("serviceWorker" in navigator) {
      navigator.serviceWorker.register("/sw.js");
    }

    // Update connection status
    function updateStatus() {
      const el = document.getElementById("status");
      el.textContent = navigator.onLine ? "Online" : "Offline";
      el.style.color = navigator.onLine ? "green" : "red";
    }

    window.addEventListener("online", updateStatus);
    window.addEventListener("offline", updateStatus);
    updateStatus();
  </script>
</body>
</html>

Key Takeaways

  • PWAs are web apps that use HTTPS, a manifest, and a service worker to deliver native-like experiences.
  • The web app manifest controls how the app appears when installed (name, icons, display mode).
  • Service workers run in the background and enable offline support by intercepting network requests.
  • The service worker lifecycle follows: register, install, activate, and fetch.
  • The app shell architecture caches the UI skeleton for instant loads, then fetches dynamic content separately.