Skip to content

v1.15 — PWA Augment

Web and desktop users can now install Objectuve as a standalone app with offline capability, while native iOS and Android builds remain authoritative for mobile.

Summary

Objectuve ships Progressive Web Application (PWA) support across three phases, adding an installable, offline-capable web surface alongside the native Capacitor apps. Web users gain the ability to install Objectuve on desktop and Android without App Store friction, with graceful offline fallback when the network is unavailable. The service worker, installation prompt, offline shell, and update flow are now production-ready.

This is an augment, not a replacement — the native iOS and Android Capacitor builds remain the primary mobile surface with push notifications and secure storage. PWA and native coexist without interference. The platform-gating idiom (!Capacitor.isNativePlatform()) ensures that all PWA code paths are inactive on native, preventing double-registration or conflicts.

Goal

Enable web and desktop users to install Objectuve as a standalone, offline-capable app. Maintain parity with native builds where feasible; intentionally diverge on features (push notifications, secure storage) where browser capabilities are insufficient. Establish the foundation for future offline-first improvements (OBJ-32 Sync Queue) across both native and web platforms.

Scope — What Shipped

  • Service Worker infrastructure — Manual registration in src/main.ts inside requestIdleCallback, gated on web platform. Non-blocking, no impact on app shell render time.
  • Web App Manifest — Generated by vite-plugin-pwa with metadata, icons (pwa-192, pwa-512, pwa-maskable-512, apple-touch-icon), theme color, and background color.
  • Workbox caching strategy — Five rules covering static assets (CacheFirst, 30d), Google Fonts stylesheets (StaleWhileRevalidate), Google Fonts files (CacheFirst, 1yr), GraphQL queries (NetworkFirst, 5min), and intentional exclusion of GraphQL mutations (always fetch from network).
  • Installation promptInstallPwaPrompt.vue surfaces install CTA on desktop Chrome/Edge/Firefox and Android Chrome when beforeinstallprompt fires. Dismissed for 7 days on user request. No CTA on iOS (users must manually "Share → Add to Home Screen").
  • Update detection and flowuseServiceWorker.ts detects new SW versions; usePwaUpdateToast.ts fires a persistent toast in PROD. On user click, the waiting SW activates and the page reloads to serve updated assets.
  • Offline shell overlayPwaOfflineOverlay.vue mounts in App.vue and shows when the network is offline for >2 seconds (grace period filters flaps). Overlay preserves session context and offers a retry button. On network return, reloads the current route.
  • Network detection composableuseNetworkStatus.ts is the canonical source of network state, shared with OBJ-32 Sync Queue. Platform-agnostic: wraps navigator.onLine on web, @capacitor/network on native.
  • PWA analyticspwaAnalytics.ts fires pwa_installed and pwa_update_applied PostHog events. Both suppressed in dev MODE and on native platforms. Enables tracking of install adoption and update acceptance.
  • Architecture and parity documentationdocs/architecture/pwa-augment.md covers SW registration, caching strategy, update flow, offline shell design, network detection contract, component/composable reference, build/manifest, rollback procedures. docs/reference/pwa-vs-native-parity-matrix.md documents 10-row feature parity table with rationale for platform-specific gaps.
  • Operations runbooks — Expanded docs/operations/deployment.md with SW cache-busting and kill-switch procedures. Updated docs/operations/mobile-builds.md with Capacitor-skips-SW note. Added PWA events schema to docs/operations/observability.md. New docs/operations/rollouts/v1.15-pwa-augment.md rollout doc with feature flags, rollout sequence, rollback steps, and PostHog monitoring queries.
  • CHANGELOG entries — Root CHANGELOG.md documents the entire milestone narrative, phase breakdown, caching rules, and operator notes. User-facing ionic_frontend/CHANGELOG.md entry: "Install Objectuve on the web — works offline, no App Store needed."

Phases

PhaseNameStatusPRsHighlights
70PWA FoundationShipped#565 (v3.9.94)Service worker + manifest, Workbox caching, useServiceWorker, useNetworkStatus
71Install UX & Update FlowShipped#570 (v3.9.96)InstallPwaPrompt, PwaOfflineOverlay, usePwaUpdateToast, App.vue wiring, featureFlags
72Docs + TelemetryShipped#576 (v3.9.97)pwaAnalytics.ts, Storybook fixes, architecture doc, parity matrix, ops runbooks, CHANGELOGs

Key Decisions

  • Augment, not replace — The PWA layer is additive. Native Capacitor builds remain authoritative for mobile; both runtimes coexist and share the same network detection interface (useNetworkStatus).
  • Platform gating via Capacitor check — All PWA code paths check !Capacitor.isNativePlatform(). This idiom is consistent with other web-only features (push notifications) and prevents double-registration or conflicts on native.
  • Service worker does not intercept mutations — GraphQL POST requests bypass the SW entirely. Mutations always go to the network; the SW only caches GET queries. The OBJ-32 Sync Queue owns mutation buffering, not the SW.
  • Overlay, not route — The offline shell is an overlay that mounts in App.vue, preserving session context (selected goal, current tab). On network return, router.go(0) reloads the current route in its network-connected state, rather than routing to a separate /offline page.
  • Graceful degradation — The PWA prompt doesn't fire on iOS Safari; offline overlay is inert on unsupported fetch APIs. Browsers that don't support beforeinstallprompt simply don't show the install CTA. No breaking errors, no polyfills.
  • Event suppression in dev and native — Both pwa_installed and pwa_update_applied are suppressed when import.meta.env.MODE === 'development' or on native platforms. This keeps PostHog clean and reflects that the events are web-only.

Requirements Coverage

No formal requirements document (PRD) exists for this milestone. The work was scoped by the epic OBJ-226 and the three phase plans. All acceptance criteria from Phase 70, Phase 71, and Phase 72 planning documents are satisfied.

Outcomes

For users:

  • Web and desktop users can install Objectuve as a standalone app without App Store friction.
  • App continues to work offline with a graceful "You're offline" overlay.
  • Updates are prompted when available; users can apply them with one click.

For operators:

  • Complete architecture and runbook documentation for the PWA layer.
  • Service worker rollback procedures (CDN cache-busting, skip-waiting escape hatch, precache invalidation).
  • PostHog event schema and monitoring queries for install adoption and update acceptance.
  • Parity matrix documenting intentional feature divergence between native and web (push, secure storage, background sync).

For the platform:

  • Foundation for OBJ-32 (Offline-First Sync Queue) — both native and web now use the same useNetworkStatus() composable.
  • Network detection contract established; future work on offline sync can rely on this canonical source.
  • Feature flag infrastructure in place (pwa_install_prompt_enabled, pwa_offline_shell_enabled) for disabling PWA surfaces without a code redeploy.

Tech Debt

  • (Phase 72) PostHog dev-project event capture: live install + update flow testing requires a deployed preview; code-level verification complete via unit tests (8/8 pwaAnalytics.test.ts), team to confirm on next preview install cycle.
  • (Phase 72) Capacitor native smoke: no regression expected (analytics gated on !isNativePlatform(), SW gate unchanged); confirm on next native build cycle.
  • f88d6906 — Merge PR #576 (Phase 72 shipped — docs + telemetry)
  • cbba9d26 — feat(pwa): add PWA analytics helper and wire install/update events
  • 5d13f2e0 — docs(v1.15/phase-72): PWA architecture doc + parity matrix
  • d416e49b — docs(v1.15/phase-72): ops runbooks, CHANGELOGs, rollout doc
  • 54294d0d — docs: correct PWA v1.15 grace period (3s → 2s) and feature flags

Last updated: 2026-05-22

Loading…