feat(ui): installable offline PWA (F5) #31

Merged
developer merged 2 commits from feature/ui-finalize-f5-pwa into development 2026-05-22 14:02:40 +00:00
Owner

F5 — PWA (installable + offline-tolerant)

From ui/PLAN-finalize.md F5 (depends on F6, now merged).

What changed

  • Service worker (src/service-worker.ts, native SvelteKit, no
    Workbox): a version-keyed cache precaches the app shell, build
    artefacts (incl. core.wasm), and static files; activate purges old
    caches (no stale code after a deploy); cache-first for build/files,
    network-first elsewhere, cached-shell fallback for offline navigations.
    The gateway is never intercepted. Registered for production only
    (kit.serviceWorker.register: false + a manual !dev register in the
    root layout) so vite dev and the dev-server e2e suite run worker-free.
  • static/manifest.webmanifest; a dependency-free generated icon set
    (scripts/gen-pwa-icons.mjs, placeholder from the favicon — swappable);
    manifest / light+dark theme-color / apple-touch tags in app.html.

Tests

New pnpm test:pwa (playwright.pwa.config.ts + tests/pwa/pwa.spec.ts)
runs against a production preview and checks: manifest + installable
icons, SW registration under a single version-keyed cache, and offline
shell load. Wired into ui-test.

Acceptance correction

"Lighthouse PWA ≥ 90" is dropped — Lighthouse removed the PWA category in
v12 (current 13.x). The Playwright checks verify the same install/offline
behaviour directly. Documented in ui/docs/pwa-strategy.md.

Verification

pnpm check 0/0; Vitest 761; PWA spec 3/3; the push CI run is green
(full e2e worker-free + PWA gate).

🤖 Generated with Claude Code

## F5 — PWA (installable + offline-tolerant) From `ui/PLAN-finalize.md` F5 (depends on F6, now merged). ### What changed - **Service worker** (`src/service-worker.ts`, native SvelteKit, no Workbox): a version-keyed cache precaches the app shell, build artefacts (incl. `core.wasm`), and static files; `activate` purges old caches (no stale code after a deploy); cache-first for build/files, network-first elsewhere, cached-shell fallback for offline navigations. The gateway is never intercepted. **Registered for production only** (`kit.serviceWorker.register: false` + a manual `!dev` register in the root layout) so `vite dev` and the dev-server e2e suite run worker-free. - `static/manifest.webmanifest`; a **dependency-free generated** icon set (`scripts/gen-pwa-icons.mjs`, placeholder from the favicon — swappable); manifest / light+dark theme-color / apple-touch tags in `app.html`. ### Tests New `pnpm test:pwa` (`playwright.pwa.config.ts` + `tests/pwa/pwa.spec.ts`) runs against a production preview and checks: manifest + installable icons, SW registration under a single version-keyed cache, and offline shell load. Wired into `ui-test`. ### Acceptance correction "Lighthouse PWA ≥ 90" is dropped — Lighthouse removed the PWA category in v12 (current 13.x). The Playwright checks verify the same install/offline behaviour directly. Documented in `ui/docs/pwa-strategy.md`. ### Verification `pnpm check` 0/0; Vitest 761; PWA spec 3/3; the push CI run is green (full e2e worker-free + PWA gate). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
developer added 2 commits 2026-05-22 13:59:37 +00:00
Native SvelteKit service worker (src/service-worker.ts): a version-keyed
cache precaches the app shell + build artefacts (incl. core.wasm) +
static files; activate purges old caches; the gateway is never
intercepted; navigations fall back to the cached shell offline. Adds
static/manifest.webmanifest, a generated placeholder icon set
(scripts/gen-pwa-icons.mjs — dependency-free pure-Node PNG encoder), and
manifest / theme-color / apple-touch tags in app.html.

Gated by Playwright against a production preview (playwright.pwa.config.ts
+ tests/pwa/pwa.spec.ts via `pnpm test:pwa`, wired into ui-test):
manifest + installable icons, SW registration + a single version-keyed
cache, and offline shell load. Lighthouse is not used — its PWA category
was removed in v12.

Docs: ui/docs/pwa-strategy.md (+ index); F5 marked done.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
fix(ui): register the service worker in production only
Tests · UI / test (push) Successful in 2m19s
Tests · UI / test (pull_request) Successful in 2m25s
11f51944df
SvelteKit's automatic SW registration also runs under `vite dev`, where
the worker intercepted/cached the dev-server e2e suite (42 failures).
Disable auto-registration (kit.serviceWorker.register: false) and
register the worker manually from the root layout guarded by `!dev`, so
`vite dev` and the e2e suite run worker-free while the production build —
and the PWA preview test — still install it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
developer merged commit 1dd8df9f6e into development 2026-05-22 14:02:40 +00:00
developer deleted branch feature/ui-finalize-f5-pwa 2026-05-22 14:02:40 +00:00
Sign in to join this conversation.