Logo
READLEARNKNOWCONNECT
Back to posts
pwa-setup

PWA Setup

ChriseJanuary 31, 2026 at 12 PM WAT

How To Turn Any Website into a Secure Progressive Web App

A step-by-step guide to turning an existing website into a secure Progressive Web App. Covers HTTPS, manifests, service workers, caching strategy, updates, and permission hygiene with practical explanations.

PWAs fixed a few long-standing web issues. No app store gatekeepers. No rewrites. Just the web, behaving better than it used to. If you’ve ever wanted your site to feel more solid, more reliable, and a little harder to break, this is for you.

A quick bit of history, because it matters. Around 2015, Google started formalizing ideas that had already been floating around for years. Offline support. Installable websites. Smarter caching. Apple followed later. The result was the PWA. Not a new platform, just a stricter way of using existing web primitives. HTTPS. Service workers. Manifests. Boring names. Powerful outcomes.

Step 1: Serve everything over HTTPS

This is non-negotiable. Service workers will not register on insecure origins. If your site still runs on plain HTTP, the browser simply refuses to play along.

Most hosting providers make this easy now. If you’re using Cloudflare, Vercel, Netlify, or a modern VPS with Let’s Encrypt, you’re probably already covered. The important thing is consistency. No mixed content. No stray HTTP images or scripts. Browsers notice. Quietly.

Step 2: Add a web app manifest

The manifest is a small JSON file that tells the browser how your site should behave when installed. Name, icon, colors, start URL. Nothing dramatic. Just metadata, but metadata browsers actually respect.

code
{
  "name": "My Website",
  "short_name": "Website",
  "start_url": "/",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#111111",
  "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 head, and that’s it. No build step required.

code
<link rel="manifest" href="/manifest.json">

Step 3: Register a service worker

This is where the real work happens. Service workers sit between your site and the network. They decide what gets cached, what gets fetched, and what happens when the network disappears.

Register it once, usually near the bottom of your main JavaScript file.

code
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js');
}

If that line feels underwhelming, good. Most good infrastructure is.

Step 4: Cache carefully, not aggressively

A big mistake people make with PWAs is caching too much, too early. A secure PWA is predictable. Users should know when content updates and when it doesn’t.

Start small. Cache your core assets. HTML shell. CSS. JavaScript bundles. Leave dynamic data alone unless you understand your invalidation strategy.

code
self.addEventListener('install', event => {
  event.waitUntil(
    caches.open('static-v1').then(cache => {
      return cache.addAll([
        '/',
        '/styles.css',
        '/app.js'
      ]);
    })
  );
});

Version your caches. Delete old ones during activation. This is not optional. Browsers remember everything.

code
self.addEventListener('activate', event => {
  const allowedCaches = ['static-v1'];

  event.waitUntil(
    caches.keys().then(keys => {
      return Promise.all(
        keys.map(key => {
          if (!allowedCaches.includes(key)) {
            return caches.delete(key);
          }
        })
      );
    })
  );
});

Step 5: Control updates explicitly

Service workers update in the background. That’s good for users and confusing for devs. A secure setup means being intentional about when new code takes over.

At minimum, handle the activate event and clean up outdated caches. More advanced setups add a refresh prompt. The key idea is respect. Don’t surprise people mid-session.

code
self.addEventListener('message', event => {
  if (event.data === 'SKIP_WAITING') {
    self.skipWaiting();
  }
});
code
// In your main app JS
if (navigator.serviceWorker) {
  navigator.serviceWorker.addEventListener('controllerchange', () => {
    window.location.reload();
  });
}

Step 6: Lock down permissions

Just because a PWA can request permissions doesn’t mean it should. Location, notifications, background sync. Ask only when necessary. Delay the prompt until the user understands why.

code
// Example: request notifications only after user action
button.addEventListener('click', async () => {
  const permission = await Notification.requestPermission();

  if (permission === 'granted') {
    new Notification('Thanks for opting in');
  }
});
code
// Optional: check permission state before asking
navigator.permissions.query({ name: 'notifications' })
  .then(result => {
    console.log(result.state);
  });

Step 7: Test the boring cases

Turn off your internet. Load the site. Refresh. Close the tab. Reopen it. Install it. Uninstall it. Update it. Break it on purpose.

A secure PWA is not the one that demos well. It’s the one that behaves sensibly when nothing goes right.

code
// Offline-first fetch handler
self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request).then(response => {
      return response || fetch(event.request);
    })
  );
});

Next Steps

From here, you can layer in background sync, smarter runtime caching, or tighter CSP headers. None of that is required on day one. The win is reliability, knowing that your site works even when the network doesn’t cooperate.

That’s what PWAs deliver. Not apps without app stores. Just the web, keeping its promises.

Tags

#offline#performance#pwa#step-by-step#tutorial#web-security

Join the Discussion

Enjoyed this? Ask questions, share your take (hot, lukewarm, or undecided), or follow the thread with people in real time. The community’s open, join us.

Published January 31, 2026Updated February 1, 2026

published

How To Turn Any Website into a Secure Progressive Web App | VeryCodedly