Files
CompanySite/.agents/frontend-specialist/PWA_IMPLEMENTATION.md
T
Clintchiz d402256547
Deploy to Production / Build & Verify (push) Failing after 5m56s
Ping Search Engines / Notify Search Engines (push) Successful in 2s
Deploy to Production / Pre-Deploy Tests (push) Has been skipped
Deploy to Production / Deploy to Railway (push) Has been skipped
Deploy to Production / Deploy to Render (push) Has been skipped
Deploy to Production / Deploy to VPS (PM2) (push) Has been skipped
Deploy to Production / Deploy to Fly.io (push) Has been skipped
Deploy to Production / Post-Deploy Verification (push) Has been skipped
Deploy to Production / Notify on Failure (push) Successful in 2s
E2E Test Suite / Critical User Journeys (push) Has been skipped
E2E Test Suite / API Integration Tests (push) Has been skipped
E2E Test Suite / Smoke Tests (P0) (push) Failing after 11m26s
E2E Test Suite / Form Interaction Tests (push) Failing after 11m42s
E2E Test Suite / Destructive & Chaos Tests (push) Failing after 12m2s
E2E Test Suite / Cross-Browser Regression (chromium) (push) Failing after 16m14s
E2E Test Suite / Cross-Browser Regression (webkit) (push) Failing after 17m45s
E2E Test Suite / Cross-Browser Regression (firefox) (push) Failing after 25m23s
E2E Test Suite / Security Header Tests (push) Failing after 7m55s
E2E Test Suite / Test Report Summary (push) Failing after 20s
E2E Test Suite / Mobile Device Tests (push) Failing after 2h49m9s
Uptime Monitor / Health & Response Time (push) Failing after 2s
Uptime Monitor / SSL Certificate (push) Successful in 2s
Uptime Monitor / Send Alerts (push) Failing after 3s
Uptime Monitor / Record Uptime Success (push) Has been skipped
First Init
2026-03-21 16:46:46 +05:30

6.7 KiB
Raw Blame History

PWA Implementation — WorkRoot IT Solutions

Overview

Progressive Web App (PWA) features have been added to the WorkRoot website. The implementation follows a progressive enhancement approach — the site works fully without JavaScript; PWA features layer on top.


Files Added / Modified

File Type Purpose
public/manifest.json New Web App Manifest (installability)
public/sw.js New Service Worker (offline + background sync)
src/pages/offline.astro New Offline fallback page
src/components/PWAInstallPrompt.astro New Install prompt banner + background sync helper
src/layouts/BaseLayout.astro Modified Links manifest, registers SW, includes install prompt
src/middleware.ts Modified CSP updated: worker-src 'self', manifest-src 'self'

Features Implemented

1. Web App Manifest (public/manifest.json)

  • Display mode: standalone (hides browser chrome when installed)
  • Theme color: #0891b2 (matches brand primary)
  • Background color: #0f172a (dark splash screen)
  • Shortcuts: Quick links to /contact and /services from the home screen
  • Icons: Uses existing apple-touch-icon.png and favicon.svg

2. Service Worker (public/sw.js)

Caching Strategies:

Request Type Strategy Details
Static assets (JS, CSS, images, fonts) Cache-first Served from cache; fetched and cached on miss
HTML pages Stale-while-revalidate Serve cache instantly, update in background
API routes (/api/*) Network-only Never cached — always fresh

Pre-cached on install:

  • / (home)
  • /offline (fallback page)
  • /manifest.json
  • /favicon.svg
  • /apple-touch-icon.png

Cache names (versioned for easy invalidation):

  • workroot-static-v1
  • workroot-pages-v1

To invalidate caches on next deploy, increment CACHE_VERSION in public/sw.js.

3. Offline Fallback (src/pages/offline.astro)

  • Served at /offline
  • Clean branded page with "Try Again" and "Go to Home" actions
  • Pre-cached by the service worker on install
  • Shown automatically when a navigation request fails offline

4. Background Sync (public/sw.js + src/components/PWAInstallPrompt.astro)

When a form submission fails due to no network:

  1. Form handler calls window.queueFormSync(url, method, body, formType)
  2. The payload is stored in IndexedDB (workroot-pwa DB, workroot-sync-queue store)
  3. A background sync tag form-sync is registered with the browser
  4. When connectivity is restored, the service worker automatically retries all queued submissions
  5. On success, clients receive a pwa:sync-success custom event they can listen to

Usage in form pages:

// In contact or newsletter form submit handler:
try {
  const res = await fetch('/api/contact', { method: 'POST', body: JSON.stringify(data) });
  if (!res.ok) throw new Error('Server error');
  // handle success
} catch {
  if (!navigator.onLine) {
    await window.queueFormSync('/api/contact', 'POST', data, 'contact');
    showMessage('You are offline. Your message will be sent when you reconnect.');
  }
}

// Listen for sync success:
window.addEventListener('pwa:sync-success', (e) => {
  if (e.detail.formType === 'contact') {
    showMessage('Your message was sent successfully!');
  }
});

5. Install Prompt (src/components/PWAInstallPrompt.astro)

  • Listens for beforeinstallprompt event (Chrome/Edge/Android)
  • Shows a non-intrusive banner after 4 seconds on first visit
  • Banner is suppressed for 7 days after dismissal (stored in localStorage)
  • Hides immediately after successful installation (appinstalled event)
  • Accessible: uses role="banner", aria-label, button labels

Security Considerations

The CSP in src/middleware.ts was updated to include:

worker-src 'self'   → allows service worker from same origin only
manifest-src 'self' → allows manifest.json from same origin only

These are deliberately restrictive — no external workers or manifests are permitted.


Offline Functionality Testing

Manual Testing in Chrome DevTools

  1. Open DevTools → Application tab
  2. Service Workers panel:
    • Confirm sw.js is registered and active
    • Use "Offline" checkbox to simulate offline
  3. Manifest panel:
    • Verify all manifest fields are correct
    • Check "Add to home screen" works
  4. Cache Storage panel:
    • Verify workroot-static-v1 and workroot-pages-v1 exist with expected entries
  5. Navigate to /contact while offline → should serve cached page
  6. Navigate to a page not in cache while offline → should show /offline

Automated Testing

The offline behavior can be tested with Playwright:

// In a Playwright test:
await context.setOffline(true);
await page.goto('/contact');
// Should either show cached page or /offline fallback

Updating the Service Worker

To force all users to get the new service worker immediately:

  1. Increment CACHE_VERSION in public/sw.js (e.g. 'v1''v2')
  2. Old caches will be deleted during the activate event
  3. skipWaiting() + clients.claim() ensure immediate takeover

Lighthouse PWA Checklist

Criterion Status
Registers a service worker
Responds with 200 when offline (cached pages + /offline fallback)
<meta name="viewport"> set (BaseLayout)
<meta name="theme-color"> set #0891b2
Web App Manifest with name, short_name, icons
Icons at 192×192 and 512×512 ⚠️ Only apple-touch-icon.png (180×180) — add larger icons for perfect score
Manifest display: standalone
HTTPS in production (HSTS enforced)
Install prompt supported

Add 192×192 and 512×512 PNG icons to public/ and reference them in manifest.json to achieve a perfect Lighthouse PWA score:

{
  "src": "/icon-192.png",
  "sizes": "192x192",
  "type": "image/png",
  "purpose": "any"
},
{
  "src": "/icon-512.png",
  "sizes": "512x512",
  "type": "image/png",
  "purpose": "any maskable"
}

Known Limitations

  • iOS Safari: Background sync is not supported. Queued forms will be retried when the user next opens the app with network access (via the SW sync event on supported platforms). On iOS, consider showing a manual retry prompt.
  • SSR + Service Worker: Since Astro runs SSR, HTML responses are dynamic. The stale-while-revalidate strategy serves potentially stale HTML while fetching fresh content in the background. This is acceptable for a marketing site.
  • API routes are always network-only. This is intentional — form submissions and the health API must never serve stale responses.