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.tsinsiderequestIdleCallback, gated on web platform. Non-blocking, no impact on app shell render time. - Web App Manifest — Generated by
vite-plugin-pwawith 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 prompt —
InstallPwaPrompt.vuesurfaces install CTA on desktop Chrome/Edge/Firefox and Android Chrome whenbeforeinstallpromptfires. Dismissed for 7 days on user request. No CTA on iOS (users must manually "Share → Add to Home Screen"). - Update detection and flow —
useServiceWorker.tsdetects new SW versions;usePwaUpdateToast.tsfires a persistent toast in PROD. On user click, the waiting SW activates and the page reloads to serve updated assets. - Offline shell overlay —
PwaOfflineOverlay.vuemounts 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 composable —
useNetworkStatus.tsis the canonical source of network state, shared with OBJ-32 Sync Queue. Platform-agnostic: wrapsnavigator.onLineon web,@capacitor/networkon native. - PWA analytics —
pwaAnalytics.tsfirespwa_installedandpwa_update_appliedPostHog events. Both suppressed in dev MODE and on native platforms. Enables tracking of install adoption and update acceptance. - Architecture and parity documentation —
docs/architecture/pwa-augment.mdcovers 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.mddocuments 10-row feature parity table with rationale for platform-specific gaps. - Operations runbooks — Expanded
docs/operations/deployment.mdwith SW cache-busting and kill-switch procedures. Updateddocs/operations/mobile-builds.mdwith Capacitor-skips-SW note. Added PWA events schema todocs/operations/observability.md. Newdocs/operations/rollouts/v1.15-pwa-augment.mdrollout doc with feature flags, rollout sequence, rollback steps, and PostHog monitoring queries. - CHANGELOG entries — Root
CHANGELOG.mddocuments the entire milestone narrative, phase breakdown, caching rules, and operator notes. User-facingionic_frontend/CHANGELOG.mdentry: "Install Objectuve on the web — works offline, no App Store needed."
Phases
| Phase | Name | Status | PRs | Highlights |
|---|---|---|---|---|
| 70 | PWA Foundation | Shipped | #565 (v3.9.94) | Service worker + manifest, Workbox caching, useServiceWorker, useNetworkStatus |
| 71 | Install UX & Update Flow | Shipped | #570 (v3.9.96) | InstallPwaPrompt, PwaOfflineOverlay, usePwaUpdateToast, App.vue wiring, featureFlags |
| 72 | Docs + Telemetry | Shipped | #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/offlinepage. - 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_installedandpwa_update_appliedare suppressed whenimport.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.
Related Artifacts
- Roadmap: v1.15-ROADMAP.md
- Milestone Audit: v1.15-MILESTONE-AUDIT.md
- Phase artifacts: .planning/milestones/v1.15-phases/
- Git tag: v3.9.97
- Phase 70 PR: #565 (v3.9.94)
- Phase 71 PR: #570 (v3.9.96)
- Phase 72 PR: #576 (v3.9.97)
Related Commits
f88d6906— Merge PR #576 (Phase 72 shipped — docs + telemetry)cbba9d26— feat(pwa): add PWA analytics helper and wire install/update events5d13f2e0— docs(v1.15/phase-72): PWA architecture doc + parity matrixd416e49b— docs(v1.15/phase-72): ops runbooks, CHANGELOGs, rollout doc54294d0d— docs: correct PWA v1.15 grace period (3s → 2s) and feature flags
Last updated: 2026-05-22