Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

Progressive Web Apps (PWA) Guide

By Kokil Thapa | Last reviewed: September 2026

A Progressive Web Apps (PWA) Guide matters because users expect fast, installable experiences without app-store friction. You can ship a PWA on top of an existing site — Laravel Blade, WordPress, WooCommerce, or a static front end — and gain offline resilience, home-screen install, and push notifications where the platform allows them. On production client projects I treat PWAs as an incremental upgrade, not a full rewrite. This guide walks through the manifest, service worker, caching strategy, testing, and deployment decisions a working engineer needs in 2026.

What are Progressive Web Apps and how do they work?

A Progressive Web App is a website that meets a small set of technical criteria. The browser treats it like an app. Users can install it. Core pages load from cache when the network drops.

Three pieces do most of the work:

  • Web App Manifest — a JSON file with name, icons, theme colour, and display mode.
  • Service Worker — a background script that intercepts network requests and manages caches.
  • HTTPS — required for service worker registration on every major browser.

PWAs are progressive by design. A browser that lacks service worker support still loads your site. You add capabilities layer by layer. That fits budget-sensitive Nepal SMB sites where a native iOS and Android pair would cost Rs 800,000–1,500,000 (~USD 6,000–11,000) before maintenance.

Progressive Web Apps (PWA) ArchitectureBrowserChrome, Safari,Firefox, EdgeWeb AppHTML, CSS,JavaScriptManifestIcons, name,display modeService WorkerFetch intercept,push, syncCache StorageShell, assets,API responsesHTTPS required for service worker registration
Progressive Web Apps (PWA) Guide — core architecture: manifest, service worker, and cache storage

The MDN Progressive Web Apps documentation remains the best neutral reference. Google’s web.dev PWA overview explains installability criteria that Lighthouse checks during audits.

On legal-tech portals and booking systems I have shipped, the PWA layer improved repeat-visit speed for logged-in users. Document upload flows still need live network validation. Offline mode covers read-only content and cached shell pages instead.

What do you need to build a PWA in 2026?

Start with a production-ready HTTPS site. Self-signed certificates fail service worker registration. Use Let’s Encrypt on Ubuntu, or a managed CDN with TLS termination.

Your build pipeline should emit static assets with content hashes. Vite 8.x (paired with Laravel 13.x or a standalone front end) produces fingerprinted JS and CSS files. Those hashes make cache-busting predictable. Node.js 26 LTS is the current LTS choice for local asset builds; many production servers still run pre-built artefacts only.

Minimum file checklist

  1. manifest.webmanifest linked from every HTML page.
  2. sw.js or service-worker.js registered from your main layout.
  3. Icons at 192×192 and 512×512 pixels (PNG or WebP).
  4. A offline fallback page — usually /offline.html.
  5. Security headers: Content-Security-Policy must allow your service worker scope.

For a Laravel 12 or 13 app, place the manifest and service worker in public/. Reference them from your master Blade layout. WordPress 7.1 sites can use a lightweight plugin or a custom theme hook. WooCommerce 11.1 storefronts benefit from caching product shells while keeping cart/checkout online-only.

Validate JSON during development. Paste your manifest into the JSON formatter tool to catch trailing commas before they break install prompts in Chrome.

Sample web app manifest

{
  "name": "Quick Grocery Orders",
  "short_name": "QuickGrocery",
  "description": "Order Nepalese groceries for local delivery",
  "start_url": "/?source=pwa",
  "scope": "/",
  "display": "standalone",
  "orientation": "portrait-primary",
  "background_color": "#ffffff",
  "theme_color": "#2b6cff",
  "icons": [
    {
      "src": "/icons/icon-192.png",
      "sizes": "192x192",
      "type": "image/png",
      "purpose": "any"
    },
    {
      "src": "/icons/icon-512.png",
      "sizes": "512x512",
      "type": "image/png",
      "purpose": "maskable"
    }
  ]
}

Link it in your HTML head:

<link rel="manifest" href="/manifest.webmanifest">
<meta name="theme-color" content="#2b6cff">
<link rel="apple-touch-icon" href="/icons/icon-192.png">

Maskable icons matter on Android. Safe-zone padding prevents logo clipping on rounded launchers. Export icons with roughly 20% inset padding around the mark.

How do you register a service worker and choose a caching strategy?

The service worker runs in its own thread. It cannot access the DOM. It listens for install, activate, and fetch events. Registration belongs in your main JavaScript bundle or an inline snippet near the end of the body.

Keep registration simple and scope it to the site root unless you have a hard reason not to:

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

For deeper patterns, read the companion post on JavaScript service workers for offline apps. It covers versioning and skipWaiting trade-offs.

Service Worker LifecycleRegisterInstallWaitingActivateFetch Event — intercept network requestsCache-first, network-first, or stale-while-revalidateCache HitReturn cached responseCache MissFetch network, update cache
Service worker lifecycle in a Progressive Web Apps (PWA) Guide — install, activate, and fetch interception

Caching strategies that survive production

Pick a strategy per asset class. Do not cache everything with one rule.

Asset typeStrategyWhy
App shell (HTML layout, core CSS/JS)Cache-first with network fallbackInstant repeat loads; update on activate
Product images and fontsStale-while-revalidateFast paint; background refresh
REST API (cart, auth, payments)Network-onlyNever serve stale payment state
Static blog contentCache-firstOffline reading for guides and FAQs

A minimal service worker for shell caching:

const CACHE = 'app-shell-v3';
const SHELL = ['/', '/offline.html', '/css/app.css', '/js/app.js'];

self.addEventListener('install', event => {
  event.waitUntil(caches.open(CACHE).then(c => c.addAll(SHELL)));
});

self.addEventListener('activate', event => {
  event.waitUntil(
    caches.keys().then(keys =>
      Promise.all(keys.filter(k => k !== CACHE).map(k => caches.delete(k)))
    )
  );
});

self.addEventListener('fetch', event => {
  if (event.request.method !== 'GET') return;
  event.respondWith(
    caches.match(event.request).then(cached => {
      return cached || fetch(event.request).catch(() => caches.match('/offline.html'));
    })
  );
});

Version the cache name on every deploy. Bump app-shell-v3 to v4 when shell assets change. Forgetting this step is the most common post-deploy bug I see. Users stay on an old cached shell until they close every tab.

Pair service worker caching with server-side Redis 8.10 or Memcached 1.6.x for API responses that are safe to cache briefly. The two layers solve different problems. See Redis caching patterns for web apps for backend cache design.

PWA vs native app vs responsive website — which should you choose?

Founders often ask for a native app when a PWA would ship faster and cost less. The decision depends on hardware access, store presence, and team skills.

CriteriaPWAResponsive websiteNative app
Install from home screenYes (browser prompt)NoYes (App Store / Play Store)
Offline supportYes, with service workerNoYes, full control
Push notificationsAndroid yes; iOS limitedNoFull platform support
Bluetooth, NFC, deep OS hooksLimited Web APIsNoFull SDK access
Development cost (typical SMB)Low — extend existing siteLowestHigh — separate codebases
SEO and link sharingFull — still a URLFullDeep links only
Store review cycleNoneNoneDays to weeks

For a florist eCommerce site like Petals Qatar flowers shop, a PWA improved mobile checkout speed without maintaining a separate Swift and Kotlin team. Payment flows still run through the live network with Khalti or card gateways — never from stale cache.

Choose native when you need background GPS tracking, complex offline SQLite, or App Store discovery as the primary acquisition channel. Choose a plain responsive site when offline mode adds no user value. Choose a PWA when repeat mobile users, flaky 4G, and home-screen presence matter.

PWA vs Native vs ResponsiveNeed installable app?NoYesResponsive SiteBrochure, blog, SEOHardware SDK?Bluetooth, NFC, etc.NoYesBuild a PWAInstall + offline + URLNative AppiOS + Android
Decision tree for choosing a PWA, responsive website, or native app in 2026

Magento 2.4.x merchants sometimes evaluate PWA Studio against lighter Hyva themes. Custom Laravel carts on projects like Quick And Easy Nepalese Grocery often reach production faster with a hand-rolled service worker than with a full PWA framework migration.

How do you test, deploy, and maintain a PWA in production?

Local testing on localhost is exempt from the HTTPS requirement. Production testing needs a staging subdomain with a valid certificate. Chrome DevTools Application tab shows manifest errors, cache contents, and service worker state.

Pre-launch audit steps

  1. Run Lighthouse PWA audits in Chrome DevTools or CI.
  2. Confirm start_url resolves with a 200 response.
  3. Test install on Android Chrome and iOS Safari (Add to Home Screen).
  4. Toggle aeroplane mode and verify offline fallback.
  5. Deploy a new shell version and confirm cache refresh after tab close.
  6. Check Core Web Vitals — LCP under 2.5s on mid-range Android hardware.

Our testing and optimization service includes Lighthouse runs and real-device checks before go-live. Speed work overlaps with speed optimization when cached shells still ship bloated JavaScript bundles.

PWA Production Deploy FlowGit PushFeature branchCI BuildVite, npm 12HTTPS DeployDeployer 7SW ActivateCache bumpProduction checks: Lighthouse PWA, offline mode, install promptMonitor GSCIndexation stableTrack CWVLCP, INP, CLS
Production deployment flow for Progressive Web Apps — CI build, HTTPS deploy, service worker activation

On Deployer 7 pipelines I maintain for sister legal-tech sites, the service worker file lives in public/sw.js inside each release. After symlink swap, set short cache headers on sw.js itself so browsers pick up updates quickly:

# Apache — in .htaccess or vhost
<Files "sw.js">
  Header set Cache-Control "no-cache, no-store, must-revalidate"
</Files>

Long-cache fingerprinted assets in /build/assets/. Never long-cache the service worker file. That mismatch causes weeks-long stale shells.

SEO and indexation

PWAs remain crawlable URLs. Googlebot executes JavaScript and sees the same manifest link as users. Avoid blocking /sw.js in robots.txt. Keep canonical tags on shell pages. Dynamic client-side routing without server fallbacks still hurts indexation.

Technical SEO for PWAs overlaps with standard site architecture. Read search engine optimization service details for schema, sitemap, and Core Web Vitals work. Optimise hero images before caching them — large PNG banners defeat the speed gains a service worker provides. See why you should optimize images for the web.

For Nepali-language storefronts, UTF-8 manifest names render correctly on Android launchers. Test Devanagari titles on a real device. The Nepali Unicode converter helps verify encoding before you paste strings into JSON.

Security considerations

Service workers control every request within their scope. A XSS vulnerability that injects into sw.js delivery becomes a persistent attack. Serve sw.js with Content-Type: application/javascript. Restrict write access to that file in CI.

Do not cache authenticated API responses unless you implement encrypted offline storage with explicit user consent. Session cookies plus cached private HTML is a data-leak vector on shared devices.

Payment callbacks from eSewa, Khalti, or Stripe must stay network-only. I follow the same rule on Laravel apps that integrate local gateways — covered in our eSewa integration guide for PHP apps.

When a PWA is the wrong tool

Skip the service worker if your site is mostly anonymous brochure content with no repeat visits. The added complexity buys nothing. Skip PWA install prompts on first visit — they annoy users who wanted a phone number.

iOS Safari supports Add to Home Screen but limits push and background sync compared to Android. Set client expectations if iOS notifications are a hard requirement.

Enterprise teams comparing platforms should read why modern businesses need progressive web apps in 2026 for business-case framing alongside this technical guide.

Key Takeaways

  • A PWA needs HTTPS, a valid manifest, and a registered service worker — nothing more for basic installability.
  • Cache shell assets cache-first; keep cart, auth, and payment endpoints network-only.
  • Bump the cache version string on every deploy and set no-cache headers on sw.js.
  • Choose PWA over native when you want install plus URL shareability without app-store overhead.
  • Audit with Lighthouse, test offline on real devices, and monitor Core Web Vitals after launch.
  • Pair frontend caching with server-side Redis or CDN rules for API-heavy Laravel or WooCommerce stores.

People Also Ask

Do Progressive Web Apps work on iPhone and Android?

Yes. Android Chrome shows an install banner when installability criteria pass. iOS Safari supports Add to Home Screen via the share menu but limits push notifications and background sync. Test both platforms before promising feature parity to stakeholders.

Does a PWA hurt SEO?

No, when implemented correctly. A PWA is still a URL-based website. Google indexes it like any other crawlable site. Problems appear only when client-side routing hides content from crawlers or offline shells replace live HTML for bots.

Can you build a PWA with WordPress or Laravel?

Yes. Place the manifest and service worker in the public web root. Register the worker from your theme footer or Blade layout. WooCommerce and Laravel eCommerce projects can cache product listing shells while keeping checkout online-only.

How much does PWA development cost in Nepal?

Adding PWA support to an existing responsive site typically runs Rs 80,000–250,000 (~USD 600–1,900) depending on offline scope, push integration, and eCommerce rules. Greenfield native apps usually cost three to five times more across iOS and Android codebases.

Ship your PWA with a clear scope

This Progressive Web Apps (PWA) Guide gives you the manifest, service worker, caching split, and deploy checklist to move from responsive site to installable app without a rewrite. Start with shell caching and a offline fallback page. Add push and background sync only when product requirements justify the maintenance cost.

Need help scoping a PWA for an existing Laravel, WordPress, or WooCommerce site? Review our web development services or e-commerce development work. Browse the portfolio for live examples. Contact us with your current stack and we will outline a phased PWA rollout that fits your budget.

Frequently Asked Questions

A Progressive Web App is a website that meets installability criteria: HTTPS, a web app manifest, and a registered service worker. Browsers treat it like an app — users can install it, repeat visits load faster from cache, and core pages may work offline.

HTTPS on every page, a valid web app manifest linked from HTML, and a registered service worker. Self-signed certificates block service worker registration in production. Localhost is exempt during development. Those three pieces unlock install prompts, offline fallback, and faster repeat visits without an app store.

Adding PWA support to an existing responsive site typically costs Rs 80,000–250,000 (~USD 600–1,900), depending on offline scope, push integration, and eCommerce rules. A native iOS and Android pair often runs Rs 800,000–1,500,000 (~USD 6,000–11,000) before maintenance.

Yes. Place manifest.webmanifest and sw.js in the public web root. Laravel 12 or 13 apps reference both from the master Blade layout. WordPress 7.1 sites use a lightweight plugin or custom theme hook. WooCommerce 11.1 storefronts can cache product listing shells while keeping cart and checkout network-only.

Choose a PWA when repeat mobile users, flaky 4G, and home-screen presence matter without app-store overhead. Choose native when you need background GPS, complex offline SQLite, or App Store discovery as primary acquisition. Choose a responsive site when offline adds no value. PWAs keep full URL shareability and SEO; native apps cost three to five times more for SMB projects.

Yes, with platform differences. Android Chrome shows an install banner when Lighthouse installability criteria pass. iOS Safari supports Add to Home Screen via the share menu but limits push notifications and background sync compared to Android. Test both on real devices before promising feature parity to stakeholders or clients.

No, when implemented correctly. A PWA remains a URL-based website that Googlebot can crawl and index like any other site. Problems appear when client-side routing hides content from crawlers, offline shells replace live HTML for bots, or you block sw.js in robots.txt. Keep canonical tags on shell pages and server fallbacks for dynamic routes.

Split strategies by asset class, not one rule for everything. Cache app shell HTML, core CSS, and JS cache-first with network fallback. Use stale-while-revalidate for product images and fonts. Keep REST API calls for cart, auth, and payments network-only — never serve stale payment state. Static blog content suits cache-first for offline reading.

Register from your main JavaScript bundle or an inline snippet after the page load event. Scope it to the site root unless you have a hard reason not to. The worker runs in its own thread, cannot access the DOM, and listens for install, activate, and fetch events. Keep registration simple and log failures during staging tests.

At minimum: name, short_name, description, start_url, scope, display mode, background_color, theme_color, and icons at 192×192 and 512×512 pixels in PNG or WebP. Include a maskable 512×512 icon with roughly 20% inset padding for Android launchers. Link it via a manifest tag and set a matching theme-color meta tag in every HTML page head.

Run Lighthouse PWA audits in Chrome DevTools or CI. Confirm start_url returns 200. Test install on Android Chrome and iOS Safari Add to Home Screen. Toggle aeroplane mode and verify the offline fallback page loads. Deploy a new shell version and confirm cache refresh after closing all tabs. Check Core Web Vitals — target LCP under 2.5s on mid-range Android hardware.

Forgetting to bump the cache version string on every deploy. Users stay on an old cached shell until they close every tab. Pair version bumps with short cache headers on sw.js itself — no-cache, no-store, must-revalidate — while long-caching fingerprinted assets in /build/assets/. Long-caching the service worker file causes weeks-long stale shells.

Service workers control every request within their scope. An XSS vulnerability that injects into sw.js delivery becomes a persistent attack — serve sw.js with Content-Type application/javascript and restrict write access in CI. Do not cache authenticated API responses unless you implement encrypted offline storage with explicit user consent. Session cookies plus cached private HTML leak data on shared devices.

No. Payment flows from eSewa, Khalti, Stripe, or card gateways must stay network-only. Cache product listing shells and static content for speed, but cart, auth, and payment endpoints always fetch live. Serving stale payment or cart state from cache creates incorrect orders and compliance problems. Document upload flows on legal-tech portals also need live network validation.

Skip the service worker if your site is mostly anonymous brochure content with no repeat visits — the complexity buys nothing. Do not show install prompts on first visit; they annoy users who wanted a phone number. If iOS push notifications are a hard requirement, set expectations early because Safari limits them. Choose native when Bluetooth, NFC, or deep OS hooks are core to the product.

Share this article

0 Comments

Leave a comment

Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

Quick Contact Options
Choose how you want to connect me: