Skip to content

pwa(first-class): harden offline reliability, lifecycle, performance, install/update UX & browser-native AI #478

Description

@qnbs

Why this exists

The PWA is not merely a compatibility fallback while native desktop migrates from Tauri to Qt. It is a first-class product surface with independent strengths: zero-install access, Chromium/WebGPU capability, browser-native storage, cross-platform reach, rapid deployment, and a real-world reference renderer for desktop differential testing.

Recent field feedback in #332 is especially useful: the reporter explicitly prefers the PWA because it remains responsive where the packaged Linux/Tauri path is problematic, and local Ollama support removed an important reason to require the desktop package. That should be treated as product signal, not merely as a Tauri workaround.

The current docs/PWA-AUDIT.md is an older v1.8-era checklist and leaves several areas as optional/verify-later. This issue establishes a modern PWA perfection/hardening program without coupling PWA progress to Qt.

Product contract

PWA, Qt, and future admitted renderers share product semantics where appropriate, but PWA is allowed to exploit browser-native capabilities where they improve the experience.

Shared product/domain semantics
        │
        ├── PWA: browser-native excellence
        └── Native: Rust Core + DesktopPlatform + Qt

Do not force artificial implementation parity. Require semantic/data-format/interoperability parity where needed, while preserving each platform's strengths.

Track A — Offline-first correctness and resilience

  • Audit the complete app shell and critical writing workflow under cold offline launch, warm offline launch, flaky network, captive/failed network, and mid-session disconnect.
  • Define which workflows are guaranteed offline versus intentionally network-dependent.
  • Verify Service Worker routing for AI/provider/inference endpoints remains network-only where caching would be unsafe or misleading.
  • Add deterministic offline fallback/error UX instead of generic browser/network failures.
  • Verify project open/edit/autosave/export/backup/relaunch with no network.
  • Exercise storage-pressure/quota failures and surface actionable, non-destructive UX.
  • Test browser eviction/persistence assumptions; request persistent storage where appropriate and explain when it is not granted.
  • Ensure offline behavior never silently loses acknowledged edits.

Track B — IndexedDB/OPFS durability, migration and recovery

Treat browser storage as a first-class persistence subsystem rather than a desktop substitute.

  • Inventory authoritative PWA stores, secondary databases, caches, model artifacts, and regenerable data.
  • Test schema upgrades from representative historical versions.
  • Add interruption/reload tests around migrations and large writes.
  • Verify encryption-at-rest boundaries and locked-session behavior against current security documentation.
  • Define corruption/recovery and factory-reset behavior without recommending destructive deletion as the first troubleshooting step.
  • Harden export/backup as a user-controlled escape hatch before risky migrations/reset operations.
  • Measure large-project save/open/migration behavior and memory pressure.
  • Where OPFS can improve large binary/model/index workloads, evaluate it deliberately rather than migrating data merely because OPFS exists.

Track C — Service Worker/update safety

  • Re-audit public/sw.js, Workbox configuration, cache versioning, runtime routes, cache expiration and invalidation.
  • Verify no sensitive AI request/response or credential-bearing URL becomes cacheable.
  • Test old-tab/new-service-worker coexistence and schema/version skew.
  • Provide clear update-ready UX with explicit reload timing; never discard unsaved/acknowledged edits to activate an update.
  • Test interrupted update, offline update check, stale cache, failed asset fetch, and rollback-compatible behavior.
  • Add CI assertions for critical caching policy and generated precache composition.
  • Keep large ONNX/DuckDB/model artifacts out of inappropriate precache paths and manage them through explicit model/cache lifecycle policy.

Track D — Performance and responsiveness budgets

The PWA should become a measured reference surface, not merely "feels faster than Tauri".

Measure representative hardware/classes for:

  • cold/warm startup;
  • time-to-interactive/editor-ready;
  • editor input latency p50/p95;
  • scroll/frame consistency;
  • Settings/Writer Studio navigation;
  • project open/save/autosave;
  • large-project behavior;
  • 30-minute and long-session memory slope;
  • background-tab/resume;
  • WebGPU/model initialization;
  • bundle/chunk transfer and parse/execute cost.

Coordinate with #450: bundle budgets should be evidence-based and user-impact-oriented. Prefer lazy loading/code splitting for genuinely cold features; do not optimize metrics by hiding required work or degrading offline correctness.

Track E — Browser-native local AI excellence

The PWA already has meaningful local-AI capability and local Ollama connectivity. Harden this as a differentiator.

  • Verify capability detection and truthful fallback across WebGPU → ONNX/WASM → Transformers/heuristics as currently supported.
  • Make model download/cache/storage footprint visible and manageable.
  • Add cancellation, timeout, memory-pressure and failed-model-load recovery.
  • Prevent concurrent model initialization storms.
  • Measure first-token/throughput separately from UI responsiveness.
  • Ensure local inference does not starve autosave/editor interaction.
  • Test offline-after-model-download behavior.
  • Harden Ollama reachability/origin/CORS error explanations without weakening browser security boundaries.
  • Never imply "local" when a selected execution path actually sends manuscript context to a cloud provider.

Track F — Installability and app-like UX

Revisit items currently marked optional in docs/PWA-AUDIT.md:

  • high-quality 192/512 maskable/any PNG assets where ecosystem/store/install surfaces benefit;
  • manifest screenshots and richer install metadata where supported;
  • contextual beforeinstallprompt UX where browser-supported, without nagging;
  • standalone/display-mode behavior;
  • launch/shortcut/share-target/protocol-handler regression tests;
  • installed-PWA window sizing/navigation/link behavior;
  • safe external-link escape behavior;
  • mobile safe areas, virtual keyboard, orientation and touch ergonomics.

Do not make installation a prerequisite: browser-tab usage remains first-class too.

Track G — Accessibility and visual robustness

Coordinate with #341 rather than treating readability as desktop-only.

  • Contrast/readability oracles for major themes and accessibility presets.
  • Keyboard-only writing/navigation flows.
  • focus restoration across dialogs/navigation/update prompts.
  • reduced-motion/transparency/high-contrast behavior.
  • zoom/text scaling and responsive layout.
  • screen-reader announcements for save/offline/update/model states.
  • mobile/virtual-keyboard editor behavior.
  • VRT across representative PWA viewport/theme combinations where stable.

Track H — Cross-browser support policy

Define a truthful support matrix rather than assuming Chromium behavior represents the Web platform.

At minimum classify current Chrome/Chromium/Edge, Firefox, Safari/macOS and mobile Safari/Chromium as:

SUPPORTED, SUPPORTED_WITH_LIMITATIONS, BEST_EFFORT, or UNSUPPORTED.

For each class document differences in installability, WebGPU/local AI, storage quotas/persistence, File System APIs, background behavior, and any feature fallbacks. Do not block valuable Chromium-native capabilities merely to simulate identical browser feature sets; degrade explicitly and safely.

Track I — Security/privacy hardening

  • Reconcile browser/PWA security claims with actual provider routing, especially Claude proxy behavior.
  • Keep credential storage, project-data encryption, collaboration crypto and cache/storage semantics distinct in UI/docs.
  • Audit CSP, worker boundaries, cross-origin isolation requirements, external navigation, share/protocol inputs and import surfaces.
  • Treat service-worker/cache poisoning and stale-code/version-skew as explicit threat/failure cases.
  • Ensure telemetry remains absent/opt-in according to product policy; performance instrumentation must not leak manuscript content.
  • Coordinate security-sensitive locale corrections with i18n: propagate desktop API-key/storage security-doc corrections to 14 remaining locales #382.

Track J — CI and release evidence

Extend CI beyond "production build succeeds":

  • installability/manifest validation;
  • Service Worker policy tests;
  • offline smoke/E2E;
  • update lifecycle test;
  • IndexedDB migration fixtures;
  • PWA accessibility smoke;
  • representative performance budgets/ratchets where deterministic;
  • browser matrix at an evidence-appropriate cadence;
  • Pages and Vercel smoke parity for routing/base-path/service-worker scope.

Coordinate executable worker/API coverage with #446 and bundle budgets with #450. Do not duplicate those issues; this issue owns the PWA acceptance contract they feed.

Track K — User-driven PWA feedback loop

Field reports from users who actually choose the PWA should be treated as primary product evidence.

When useful, ask for small, privacy-safe observations, not giant debug dumps:

  • browser/version and OS;
  • installed PWA vs normal tab;
  • online/offline state;
  • approximate project size;
  • whether local AI/Ollama/cloud AI was active;
  • exact workflow and visible symptom;
  • screenshot when content can be safely redacted.

Never ask users to post manuscript content, API keys/tokens, encryption material, private paths, full storage dumps, or sensitive provider payloads.

Relationship to #332 / Qt migration

#332 should use PWA as a reference renderer/baseline, but this issue goes further: PWA has its own excellence roadmap.

Qt success does not retire or freeze PWA. Conversely, PWA-specific improvements should not contaminate the DesktopPlatform boundary with browser APIs. Shared fixes belong in shared/domain layers when truly portable; browser-specific excellence stays behind browser/PWA boundaries.

Cross-renderer comparison should help find portable regressions, not reduce PWA to a lowest-common-denominator implementation.

Suggested evidence matrix

Capability Browser tab Installed PWA Offline Large project Local AI Mobile
launch/open project n/a
edit/autosave/relaunch coexist
update lifecycle degraded-safe coexist
export/backup ✓ where local n/a verify
AI local/cloud routing truthful capability-based
storage recovery model cache
accessibility status UX

Definition of done

Non-goals

  • forcing PWA to emulate native OS integration;
  • forcing Qt to embed a web renderer to preserve PWA implementation details;
  • introducing browser APIs into native Core/DesktopPlatform contracts;
  • sacrificing offline safety/security for Lighthouse scores;
  • treating Chromium-only local-AI acceleration as a reason to make basic writing functionality Chromium-only.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions