Progressive Web App (PWA) Development for Mobile
Client wants mobile presence without publishing to App Store and Google Play. Or they already have a website on React/Vue/Angular and need to add offline mode, push notifications and home screen icon — without rewriting everything from scratch. PWA covers this request, but «just add manifest.json» — that's not PWA.
Real PWA — Service Worker with proper caching strategy, Web App Manifest with correct parameters for each platform, and HTTPS without exceptions. Miss any of these three — get app that doesn't install or works incorrectly offline.
Where usually breaks
Service Worker and caching strategies. Most common mistake — cache everything with CacheFirst without invalidation. User opens updated app but sees old version because sw.js serves resources from stale cache. Workbox solves this via StaleWhileRevalidate for statics and NetworkFirst for API requests, but must clearly separate what to cache aggressively (fonts, icons, hashed JS bundles) from what to always request fresh (user data, inventory, content).
Separate story — background sync via Background Sync API. User submitted form offline, Service Worker intercepted request and put in SyncManager. When connection restored — request went. Looks simple, but registration.sync.register('sync-orders') works only in Chrome/Android. On iOS Safari Background Sync still unsupported — must account for this when designing offline scenarios.
iOS Safari and its limitations. Apple systematically restricts PWA: before iOS 16.4 push notifications in PWA didn't work at all. Now work, but only if app added to home screen via Safari — not from Chrome, not from Firefox. IndexedDB storage quota on iOS — 50 MB default, against gigabytes on Android. Must calculate cached resources beforehand.
How we build PWA
Foundation — Workbox 7.x, built into Vite via vite-plugin-pwa. generateSW configuration covers 80% of cases: plugin automatically creates precache manifest from bundle and registers Service Worker. For complex scenarios — injectManifest mode with manual sw.js.
Manifest for correct installation on both platforms requires minimum: name, short_name, start_url with ?source=pwa parameter, display: standalone, theme_color, background_color, and icon set — 192×192 and 512×512 in PNG, plus maskable variant for Android Adaptive Icons. Without maskable icon on Android shows with white background in circle — looks unprofessional.
Push notifications via Web Push Protocol: VAPID keys generated once, public key transmitted to client on subscribe via PushManager.subscribe(). On server — web-push library for Node.js or equivalent. Subscription object with endpoint, p256dh and auth saved in DB — exactly it's needed for sending.
// Subscribe registration
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(PUBLIC_VAPID_KEY)
});
Installability. Chrome shows «Add to home screen» banner when criteria met: HTTPS, valid manifest, registered SW with fetch handler. Lighthouse checks all conditions. On iOS installation only manual via Share → «Add to Home Screen» — no automatic prompts.
To measure install conversion use beforeinstallprompt event: intercept it, defer via event.preventDefault(), show own UI when needed, then call prompt(). This gives control over when and to whom to suggest installation.
What's included in work
Audit existing frontend — performance (Core Web Vitals), HTTPS config, current Service Worker if exists. Development SW with caching strategies for specific routes. Manifest, icons all sizes, iOS splash screens. Push notifications if needed. Testing offline scenarios in Chrome DevTools (Application → Service Workers → Offline) and on real devices.
Verify result via Lighthouse PWA audit — all points should be green.
Timelines
Adding PWA to ready web app: 3–7 days. Developing PWA from scratch with offline logic and push notifications: 2–4 weeks. Cost calculated after analyzing current stack and offline functionality requirements.







