Mobile Development Intermediate

Building Progressive Web Apps (PWAs)

Create fast, reliable, and engaging mobile experiences using Progressive Web App technology — installable on a home screen, working offline, without the cost of separate iOS and Android apps.

JB Jahid Babu — Laravel Developer September 16, 2026 8 min read
Service Workers Web App Manifest Offline-First HTTPS

1What Makes an App a "Progressive Web App"

A PWA is a regular website that meets a specific technical bar: it's served over HTTPS, has a web app manifest, and registers a service worker. Meeting that bar unlocks capabilities normally reserved for native apps — offline functionality, home-screen installation, push notifications, and app-like full-screen navigation — while still being a single codebase that runs in any browser.

For businesses evaluating a mobile presence, a PWA is often the fastest and cheapest path to something that feels like an app, without the App Store/Play Store approval process, native codebases, or per-platform maintenance burden.

2The Three Core Ingredients

  1. HTTPS — required; service workers won't register on plain HTTP (localhost is exempted for development)
  2. Web App Manifest — a JSON file describing the app's name, icons, colors, and launch behavior
  3. Service Worker — a background script that intercepts network requests, enabling caching and offline support

3Step 1 — The Web App Manifest

Create manifest.json in your public root:

manifest.json
{
  "name": "JTechBD POS",
  "short_name": "JT POS",
  "start_url": "/",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#0f172a",
  "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>:

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

4Step 2 — The Service Worker

Register the service worker from your main JavaScript file:

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

A minimal sw.js that caches core assets on install:

sw.js
const CACHE_NAME = 'app-cache-v1';
const CORE_ASSETS = ['/', '/offline.html', '/css/app.css', '/js/app.js'];

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

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

5Step 3 — Caching Strategies

Different content needs different caching logic — don't use one strategy for everything:

StrategyBest for
Cache-firstStatic assets (CSS, JS, fonts, logos) that rarely change
Network-first, fall back to cacheContent that should be fresh when online but still usable offline (product listings, dashboards)
Stale-while-revalidateServe cached instantly, update cache in the background for next time
sw.js — network-first
self.addEventListener('fetch', (event) => {
  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))
  );
});

6Making It Installable

Once the manifest and service worker are in place, most browsers will offer an install prompt automatically. You can also trigger a custom "Install App" button:

app.js
let deferredPrompt;
window.addEventListener('beforeinstallprompt', (e) => {
  e.preventDefault();
  deferredPrompt = e;
  document.getElementById('install-btn').hidden = false;
});

document.getElementById('install-btn').addEventListener('click', async () => {
  deferredPrompt.prompt();
  await deferredPrompt.userChoice;
  deferredPrompt = null;
});

7PWA vs Native App: When to Choose Which

Choose a PWA when:

Choose native (or a hybrid framework) when:

From our own projects Many of our client SaaS products — including our POS systems — are built as PWAs first, since store owners primarily need reliable offline checkout on a tablet, not App Store distribution.

Want a Progressive Web App for your business?

We build PWAs — POS, booking, client portals — as part of our software development services.

Get Free Quote →

8Frequently Asked Questions

Do PWAs work on iOS?

Yes, with some limitations — Safari supports service workers and home-screen installation, but push notifications and some background sync features have historically lagged behind Android/Chrome. Always test on real iOS devices before launch.

Can a PWA fully replace a native app?

For most content-driven and business apps (POS, booking systems, dashboards), yes. For apps requiring deep native integrations or App Store visibility as a core growth channel, a native or hybrid approach is still better.

Is a PWA good for SEO?

Yes — since a PWA is still a normal website under the hood, it's fully crawlable and indexable, unlike a native app whose content lives behind an app store wall.

JB
Jahid Babu — Laravel Developer, Rangpur BD

14+ years building PHP and Laravel applications for clients across Bangladesh, UK, Germany and the Netherlands.