Derived from docs/issues/46-perf-budget-lighthouse.md — the canonical source of truth. Execution order & dependencies: docs/ISSUE_PLAN.md (PR #1). If this issue and the doc disagree, the doc wins.
Summary
Add Lighthouse CI (mobile profile) against the built app with the §14 budgets as assertions, plus
bundle-size tracking, and fix any budget violations found.
Context
DESIGN §14. MapLibre is heavy; without an enforced budget the app drifts past mobile usability.
This lands late (after all features) to measure the real v1.
Scope
- Dev dep
@lhci/cli; lighthouserc.json: collect against npm run preview URL (built app,
SW active), settings: mobile emulation, simulated 4G; assert category scores:
performance ≥ 90, pwa: all installable audits pass, accessibility ≥ 90 (41 made it true),
best-practices ≥ 95; budgets: script ≤ 350 KB gzip, stylesheet ≤ 40 KB, total ≤ 600 KB
(excluding stubbed tiles — LHCI hits real page: ensure tile hosts unreachable→graceful? No:
run LHCI with --collect.settings.blockedUrlPatterns for tile/API hosts so runs are hermetic
and §13 offline states render — document that performance is measured on the shell).
- CI: separate workflow job
lighthouse in ci.yml on PRs (needs build artifact; non-flaky config:
3 runs, median); continue-on-error: false.
- Bundle report:
vite build rollup output sizes echoed + compared in the job log; hard gate via
LHCI budgets only (single source of truth).
- Fix violations found (likely: code-split About/onboarding via dynamic import — 42 already lazy;
verify; MapLibre is the floor — document actual numbers in PR).
Detailed Requirements
- Hermetic runs: no real upstream requests (blocked patterns); document that field performance
with tiles is tracked manually at release (48's device matrix).
- Budgets live in lighthouserc.json only (no duplicated constants).
- Flake policy: median-of-3; if perf score flakes ±3 around 90 in CI hardware, set 87 with a
dated TODO to restore 90 — decision recorded in the PR (conservative, explicit).
Acceptance Criteria
Validation
CI job on the PR; local npx lhci autorun documented in CONTRIBUTING (45's file — append).
Dependencies
06 (build/base), 31 (SW), 41 (a11y score), most features merged (measures reality).
Non-goals
Real-network field metrics (manual at 48), RUM/analytics (never), image optimization pipeline
(icons are already tiny).
Design References
DESIGN §14, §15, §16.
Summary
Add Lighthouse CI (mobile profile) against the built app with the §14 budgets as assertions, plus
bundle-size tracking, and fix any budget violations found.
Context
DESIGN §14. MapLibre is heavy; without an enforced budget the app drifts past mobile usability.
This lands late (after all features) to measure the real v1.
Scope
@lhci/cli;lighthouserc.json:collectagainstnpm run previewURL (built app,SW active), settings: mobile emulation, simulated 4G;
assertcategory scores:performance ≥ 90, pwa: all installable audits pass, accessibility ≥ 90 (41 made it true),
best-practices ≥ 95; budgets: script ≤ 350 KB gzip, stylesheet ≤ 40 KB, total ≤ 600 KB
(excluding stubbed tiles — LHCI hits real page: ensure tile hosts unreachable→graceful? No:
run LHCI with
--collect.settings.blockedUrlPatternsfor tile/API hosts so runs are hermeticand §13 offline states render — document that performance is measured on the shell).
lighthousein ci.yml on PRs (needs build artifact; non-flaky config:3 runs, median);
continue-on-error: false.vite buildrollup output sizes echoed + compared in the job log; hard gate viaLHCI budgets only (single source of truth).
verify; MapLibre is the floor — document actual numbers in PR).
Detailed Requirements
with tiles is tracked manually at release (48's device matrix).
dated TODO to restore 90 — decision recorded in the PR (conservative, explicit).
Acceptance Criteria
pasted in PR.
committed).
Validation
CI job on the PR; local
npx lhci autorundocumented in CONTRIBUTING (45's file — append).Dependencies
06 (build/base), 31 (SW), 41 (a11y score), most features merged (measures reality).
Non-goals
Real-network field metrics (manual at 48), RUM/analytics (never), image optimization pipeline
(icons are already tiny).
Design References
DESIGN §14, §15, §16.