
September 12, 2026
12 min read
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.
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
manifest.webmanifestlinked from every HTML page.sw.jsorservice-worker.jsregistered from your main layout.- Icons at 192×192 and 512×512 pixels (PNG or WebP).
- A offline fallback page — usually
/offline.html. - Security headers:
Content-Security-Policymust 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.
Caching strategies that survive production
Pick a strategy per asset class. Do not cache everything with one rule.
| Asset type | Strategy | Why |
|---|---|---|
| App shell (HTML layout, core CSS/JS) | Cache-first with network fallback | Instant repeat loads; update on activate |
| Product images and fonts | Stale-while-revalidate | Fast paint; background refresh |
| REST API (cart, auth, payments) | Network-only | Never serve stale payment state |
| Static blog content | Cache-first | Offline 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.
| Criteria | PWA | Responsive website | Native app |
|---|---|---|---|
| Install from home screen | Yes (browser prompt) | No | Yes (App Store / Play Store) |
| Offline support | Yes, with service worker | No | Yes, full control |
| Push notifications | Android yes; iOS limited | No | Full platform support |
| Bluetooth, NFC, deep OS hooks | Limited Web APIs | No | Full SDK access |
| Development cost (typical SMB) | Low — extend existing site | Lowest | High — separate codebases |
| SEO and link sharing | Full — still a URL | Full | Deep links only |
| Store review cycle | None | None | Days 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.
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
- Run Lighthouse PWA audits in Chrome DevTools or CI.
- Confirm
start_urlresolves with a 200 response. - Test install on Android Chrome and iOS Safari (Add to Home Screen).
- Toggle aeroplane mode and verify offline fallback.
- Deploy a new shell version and confirm cache refresh after tab close.
- 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.
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
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.

