deer-flow/docs/superpowers/plans/2026-07-31-frontend-performance-baseline-delivery.md
DanielWalnut 459dd78707
perf(frontend): bound delivery, bundles, and long-running UI work (#4622)
* docs: design frontend performance remediation

* docs: plan frontend performance remediation

* test(frontend): add route asset performance budgets

* perf(nginx): compress textual responses safely

* perf(frontend): lazy load case study media

* perf(frontend): bound static demo file tracing

* perf(frontend): restore static locale boundaries

* perf(frontend): defer closed workspace panels

* perf(frontend): split editors and deduplicate highlighting

* perf(frontend): index incremental message derivation

* perf(frontend): stabilize paged history cache policy

* perf(frontend): bound streaming markdown renders

* perf(frontend): virtualize message history

* perf(frontend): bound and virtualize chat lists

* perf(frontend): suspend inactive decorative animation

* perf(browser): stream latest frames as binary

* perf(artifacts): stream bounded text previews

* docs: finalize performance runtime boundaries

* style(backend): apply test formatting

* fix(frontend): keep translation functions client-side

* perf(frontend): defer decorative animation bundles

* test(frontend): lock optimized route budgets

* fix: harden frontend performance boundaries

* test(frontend): update i18n provider fixture

* fix(frontend): preserve sidebar pagination position

* style(backend): format artifact range test
2026-08-01 22:19:59 +08:00

6.9 KiB

Frontend Performance Baseline and Delivery Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Turn the current route-weight and delivery findings into repeatable gates, enable safe compression, eliminate eager case-study image downloads, and remove the mock route's whole-project trace.

Architecture: A production-server measurement script owns route asset accounting and compares it with a checked-in budget. Nginx owns textual response compression. Landing images become semantic lazy images. Static demo data is exposed through an explicit manifest so route handlers never derive filesystem paths from request input.

Tech Stack: Next.js 16, TypeScript, Rstest, Node.js, Nginx, pnpm.

Global Constraints: Work only in /Users/minimax/workspace/deer-flow/.worktrees/fix-frontend-performance. Preserve current API routes. Do not gzip SSE or already-compressed media. Every fix follows RED, GREEN, regression proof, then commit.

Task 1: Add a reproducible route-asset budget gate

Files:

  • Create: frontend/scripts/measure-route-assets.mjs

  • Create: frontend/performance-budgets.json

  • Create: frontend/tests/unit/scripts/measure-route-assets.test.ts

  • Modify: frontend/package.json

  • Modify: frontend/AGENTS.md

  • Write a failing unit test for exported extractAssetPaths(html) and evaluateBudgets(measurements, budgets). Assert duplicate scripts are counted once and a one-byte overage fails with the route, asset class, actual bytes, and limit.

  • Run cd frontend && pnpm test -- tests/unit/scripts/measure-route-assets.test.ts and record the missing-module failure.

  • Implement pure helpers in measure-route-assets.mjs. The CLI must build with NEXT_PUBLIC_STATIC_WEBSITE_ONLY=true, spawn next start on a free local port, fetch /, /workspace/chats, the canonical demo thread, /en/docs, and /blog/posts, resolve referenced /_next/static/ files under .next/static, and emit performance-results.json.

  • Check in these initial ceilings, all below the measured baseline: / JS 1,050,000 and CSS 150,000; /workspace/chats JS 2,750,000 and CSS 150,000; demo chat JS 3,500,000 and CSS 150,000; /en/docs and /blog/posts JS 3,000,000 and CSS 230,000.

  • Add "perf:check": "node scripts/measure-route-assets.mjs --check" and document the gate and static-demo requirement in frontend/AGENTS.md.

  • Run the focused test GREEN. Temporarily lower the / JS budget to 1, prove pnpm perf:check fails, restore the file, and defer the final passing gate until the bundle plan lands.

  • Commit: test(frontend): add route asset performance budgets.

Task 2: Enable safe Nginx compression

Files:

  • Modify: docker/nginx/nginx.conf

  • Modify: docker/nginx/nginx.local.conf

  • Create: backend/tests/test_nginx_compression.py

  • Modify: AGENTS.md

  • Write a failing test that parses both configs and asserts the same compression policy: gzip on, gzip_vary on, minimum length 1024, compression level 5, and types limited to HTML default plus CSS, JavaScript, JSON, XML, and SVG. Assert text/event-stream, fonts, images other than SVG, audio, and video are absent.

  • Run cd backend && uv run pytest tests/test_nginx_compression.py -q and capture RED.

  • Add the identical directives to both http blocks. Include gzip_proxied any; do not add a wildcard content type.

  • Update the service-topology note in root AGENTS.md to state that Nginx compresses textual responses but deliberately excludes SSE and pre-compressed media.

  • Run the focused test GREEN. If local Nginx is available, start the configured service and verify curl --compressed -I returns Content-Encoding: gzip for HTML while an SSE response is uncompressed.

  • Revert the directive block, prove the test fails, restore it, rerun GREEN.

  • Commit: perf(nginx): compress textual responses safely.

Task 3: Lazy-load landing case-study images

Files:

  • Modify: frontend/src/components/landing/sections/case-study-section.tsx

  • Create: frontend/tests/unit/components/landing/case-study-section.dom.test.tsx

  • Write a DOM test that renders the section and asserts each card has an actual img with loading="lazy", decoding="async", intrinsic dimensions, descriptive alt text, and no inline/background-image URL.

  • Run the focused test and capture RED against the CSS backgrounds.

  • Replace background-image cards with a positioned next/image or native image. Keep the overlay and visual crop, set explicit sizes, and make only an above-the-fold image eager if measurement proves it is visible on initial viewport.

  • Run the DOM test GREEN and verify in a browser/network trace that offscreen JPEG requests do not start before scrolling.

  • Revert the component change, prove RED, restore, rerun GREEN.

  • Commit: perf(frontend): lazy load case study media.

Task 4: Replace request-derived mock filesystem traversal with a static manifest

Files:

  • Modify: frontend/src/core/threads/static-demo.ts

  • Modify: frontend/src/app/mock/api/threads/[thread_id]/artifacts/[[...artifact_path]]/route.ts

  • Modify: frontend/src/app/mock/api/threads/[thread_id]/history/route.ts

  • Modify: frontend/src/app/mock/api/threads/search/route.ts

  • Modify: frontend/src/app/workspace/page.tsx

  • Create: frontend/tests/unit/core/threads/static-demo.test.ts

  • Create: frontend/tests/unit/app/mock/static-artifact-route.test.ts

  • Add failing tests for resolveStaticDemoArtifact(threadId, segments) covering a known artifact, unknown thread, traversal segments, and encoded traversal. Add a route test that asserts the response comes from the manifest-backed resolver.

  • Run both focused tests and capture RED.

  • Define an explicit immutable demo manifest in static-demo.ts; normalize and validate all path segments before a lookup. Route handlers may read only paths returned by that manifest.

  • Replace request-time readdirSync, readFileSync, and statSync in mock routes/workspace discovery with manifest imports or fs/promises during server execution. Keep response payloads byte-for-byte compatible.

  • Run focused tests GREEN.

  • Run NEXT_PUBLIC_STATIC_WEBSITE_ONLY=true pnpm build and assert the prior Turbopack "whole project unintentionally traced" warning and mock artifact import trace are absent.

  • Revert the resolver use, prove the route test RED, restore, rerun focused tests and build.

  • Commit: perf(frontend): bound static demo file tracing.

Final verification

  • Run cd frontend && pnpm check && pnpm test.
  • Run cd backend && uv run pytest tests/test_nginx_compression.py -q.
  • Run the static-demo production build and confirm zero unexpected-file/whole-project trace warnings.
  • Record the new route measurements in the PR description; do not loosen a budget to make the gate pass.