Skip to content

perf(forge-shell): Lighthouse 68→76 + CI workflow + flag flip#25

Merged
HieuNTg merged 4 commits into
masterfrom
perf/forge-shell
May 13, 2026
Merged

perf(forge-shell): Lighthouse 68→76 + CI workflow + flag flip#25
HieuNTg merged 4 commits into
masterfrom
perf/forge-shell

Conversation

@HieuNTg

@HieuNTg HieuNTg commented May 13, 2026

Copy link
Copy Markdown
Owner

Summary

Sprint perf/forge-shell — lift Lighthouse desktop perf on #pipeline / #library / #reader.

Outcome: 68-69 → 76 perf (+8). Gap to ≥85 documented and deferred (next-sprint scope).

Stage Perf FCP (ms) LCP (ms) Notes
Baseline 68-69 Pre-sprint
M1 (P1+P2+B0) 77 1849 2556 Alpine self-host + script bundling + x-show→x-if
M2-A (extract CSS) 73 2217 2581 regression — StaticFiles doesn't gzip; reverted
M2-B (B1 re-inline) 76 1886 2538 inline CSS rides HTML gzip path

Shipped

  • P1 — Alpine self-host — vendor web/vendor/alpine/alpine.min.js, eliminate CDN cold-start
  • P2 — Runtime bundlescripts/build-runtime-bundle.mjsweb/dist/js/runtime-bundle.min.js; npm run build chains tsc + bundle
  • B0 — Lazy mount — 4 routes (#library, #export, #providers, #guide) converted x-show<template x-if>
  • F — Flag flipSTORYFORGE_FORGE_UI default → true; tests updated (10/10 pass); flag + dead-branch checks queued for removal next sprint per CLAUDE.md §8
  • P4 — Lighthouse CIlighthouse-budget.json + .github/workflows/lighthouse.yml (warn-only, continue-on-error: true, PR + workflow_dispatch, 3 routes, $GITHUB_STEP_SUMMARY, 14-day artifact retention)

Reverted

  • P3'-A — External critical CSS — root cause: FastAPI StaticFiles does not run GZipMiddleware (confirmed via Invoke-WebRequest headers showing empty Content-Encoding and raw Content-Length: 17157). Extraction added a render-blocking un-gzipped request, regressing FCP 1849 → 2217. Re-inlined in B1.

Deferred to next sprint

Gap to ≥85 is dominated by:

  1. Tailwind CSS payload (~18KB gz / ~80KB raw) — needs purging pass + tree-shake
  2. Inter font CDN — needs self-host with font-display: swap + WOFF2 subset

Either is its own diff worth of risk. Out of sprint scope.

Test plan

  • npx vitest run web/js/__tests__/feature-flags.test.ts → 10/10 pass
  • npm run build (tsc + bundle) → succeeds
  • Backend /api/health poll smoke (CI workflow shape)
  • M2-B Lighthouse run captured in plans/reports/lh-p3prime-b1/
  • CI: first lighthouse.yml run on this PR will populate $GITHUB_STEP_SUMMARY (warn-only)
  • Manual smoke on staging: #library lazy mount, #export lazy mount, runtime bundle loads with defer

CLAUDE.md compliance

  • §5 evidence-backed deltas (Lighthouse JSON under plans/reports/)
  • §6 root cause for StaticFiles gzip gap (diagnosed via headers)
  • §8 flag removal queued for next sprint
  • §12 diff-led reporting

HieuNTg added 4 commits May 13, 2026 16:13
- Vendor alpine.min.js under web/vendor/alpine/ to eliminate CDN cold-start
- Add scripts/build-runtime-bundle.mjs producing web/dist/js/runtime-bundle.min.js
- npm run build now chains tsc + bundle step
- Track the prebuilt runtime bundle (rebuild on container boot adds ~3s startup)
- .gitignore: re-include web/dist/js/runtime-bundle.min.js via parent-dir negation

Part of perf/forge-shell sprint, Lighthouse desktop perf 68-69 -> 76 (+8).
#library, #export, #providers, #guide pages now lazy-mount via Alpine's
<template x-if> instead of always-rendered x-show. Reduces initial DOM
tree size; pages only mount when active.

Net Lighthouse impact (M1): perf 68-69 -> 77, FCP 1849ms.
Forge UI redesign has shipped end-to-end across the sprint. Per CLAUDE.md §8,
flag and its dead-branch checks queue for removal next sprint.

- isForgeUiEnabled() returns true by default (was false)
- Resolution order unchanged: window global > localStorage > default
- Tests in feature-flags.test.ts updated for new default; 10/10 pass
- lighthouse-budget.json: FCP 2000 / LCP 2800 / TBT 200 / CLS 0.1 /
  SI 2200 / TTI 3000; script 200KB, stylesheet 80KB, total 600KB;
  third-party count 10
- .github/workflows/lighthouse.yml: continue-on-error: true, runs on
  PR touching web/**, app.py, requirements.txt, package.json, the
  workflow, or the budget file. Builds runtime bundle, starts backend
  with dummy OPENAI key, polls /api/health, runs Lighthouse on
  pipeline/library/reader with --preset=desktop --budget-path,
  emits scores to $GITHUB_STEP_SUMMARY, uploads lh-reports/ artifact
  (14-day retention).

Warn-only by design: the sprint target (perf >=85) is not yet hit
(currently 76). CI signals regressions without blocking merges.
@HieuNTg HieuNTg merged commit 873a04f into master May 13, 2026
1 check passed
@HieuNTg HieuNTg deleted the perf/forge-shell branch May 13, 2026 09:18
HieuNTg added a commit that referenced this pull request Jun 22, 2026
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant