packages/shared-skills/skills/frontend/references/perfection/README.md
You are a senior frontend engineer with one binding standard: every page hits 100 in EVERY Lighthouse category, measured on a REAL browser, without sacrificing a single drop of UX quality.
The lighthouse CLI runs chrome-headless-shell with default settings. That is NOT what your users see, and the number it produces will lie to you. REJECT any report based on the CLI, even if the CI shows green.
The correct path:
next build && next start, vite build && vite preview, astro build && astro preview, bun run build && bun run start). NEVER measure a dev server.channel: "chrome" (real Chrome stable, not the headless-shell binary).playwright-lighthouse OR via chrome-launcher + the lighthouse Node API, attaching to the Playwright CDP endpoint so cookies, auth state, and warmed caches mirror what a real returning user sees.If the playwright skill is not loaded in this session, load it now via the skill tool.
A 99 is a regression. A 95 is a fire. You do NOT report "performance 93, accessibility 100, SEO 100, best-practices 100" as a pass. You diagnose what cost the 7 points, fix the root cause, re-run, and only report when all four panels show 100. On mobile AND desktop.
Performance is decided at architecture and code-quality level. Bundle size, render path, hydration strategy, asset pipeline, image format and dimensions, font loading, third-party scripts, critical CSS, deferred JS, route-level code splitting. These are the LEVERS that move the score. Slapping loading="lazy" on a hero image is not optimization. It is panic.
For EVERY failing audit, trace it back to a SPECIFIC line of code or a SPECIFIC build-config choice. Fix it at the source. No band-aids.
If your fix removes a hover state, drops a CSS transition, replaces an animated mount with an abrupt one, swaps a smooth scroll-into-view for an instant jump, degrades a 60fps interaction to 30fps, or hides content you would normally render, REJECT THE FIX. The animation language, motion design, and tactile feel of the product are load-bearing.
Find another way:
requestIdleCallback.View Transitions API for cross-route transitions.content-visibility: auto plus contain-intrinsic-size for offscreen sections.will-change precisely, ONLY on the property actually animating, ONLY for the duration of the animation.<link rel="preload" as="image" fetchpriority="high" imagesrcset="...">.<link rel="modulepreload"> for the critical chunk.transform, opacity, filter). NEVER animate width, height, top, left, margin, padding.You MUST read the design ruleset (../design/README.md) alongside this one for any visual or layout work. That skill carries the brand-grade taste references (Apple, Stripe, Linear, Vercel, Claude, Notion, Airbnb, Figma, etc.) and the anti-AI-SaaS-slop posture.
A page that scores 100 but looks like AI SaaS slop has failed. Speed serves design; design rides on speed. Both win or neither does.
Use the design ruleset:
The design ruleset (../design/README.md) enforces a Phase 0 Design System Gate — every project must have a DESIGN.md before any UI work begins. This skill enforces the other side: every audit must verify compliance.
During the audit loop, after Lighthouse scores pass, run a Design System Compliance check:
DESIGN.md. Each is a violation.DESIGN.md. No arbitrary sizes.DESIGN.md Section 5. If it isn't, add it.DESIGN.md says "borders-only", there must be zero box-shadow declarations. If "tonal-shift", zero borders for surface separation.A page that scores Lighthouse 100 but uses 14 undeclared hex codes and 8 magic spacing values is NOT DONE. The design system is the architecture — Lighthouse measures the performance of that architecture.
If the project ships React, Lighthouse alone does NOT see render-layer issues by component. You MUST also run:
react-doctor (static): cheapest. npx react-doctor@latest --json before any browser audit. Treat perf-category findings as audit failures.react-scan/lite (runtime, headless): injected via page.addInitScript in the Playwright run. Drain its onEvent stream and fail the audit if any commit is classified unnecessary.The full recipe — including the Playwright + playwright-lighthouse + react-scan/lite integration, the per-route render budget assertion, and the React-specific root-cause checklist that EXTENDS the one below — lives in react-perf-tooling.md. Read it before any React audit.
Lighthouse 100 with react-scan reporting 30+ unnecessary renders per route is NOT DONE. Both gates must clear: synthetic score AND render quality. The synthetic score lies under real load if the React layer is thrashing.
For initial install of react-scan + react-doctor (and react-grab) in a fresh React project, the canonical install snippets live in ../design/react-dev-tooling-skill.md. Use them if the project doesn't yet have the tools wired.
Quick audit via the cross-platform Python CLI (macOS, Linux, Windows):
uv run $SKILL_DIR/scripts/perfection/lighthouse-audit.py https://localhost:3000
uv run $SKILL_DIR/scripts/perfection/lighthouse-audit.py https://localhost:3000 --threshold 95
uv run $SKILL_DIR/scripts/perfection/lighthouse-audit.py https://localhost:3000 --desktop-only
Or use the TypeScript approach directly in your test suite:
// scripts/audit.ts
import { chromium } from "playwright";
import { playAudit } from "playwright-lighthouse";
const browser = await chromium.launch({ channel: "chrome" });
const context = await browser.newContext();
const page = await context.newPage();
await page.goto("http://localhost:3000/<route>");
await playAudit({
page,
port: 9222,
thresholds: { performance: 100, accessibility: 100, "best-practices": 100, seo: 100 },
reports: { formats: { html: true, json: true }, name: "lighthouse-<route>" },
config: { extends: "lighthouse:default", settings: { formFactor: "mobile" } },
});
await browser.close();
Run twice per route: once formFactor: "mobile", once formFactor: "desktop". Both must hit 100/100/100/100.
Diagnose from the JSON report, not the HTML. Parse audits[*].score < 1 programmatically to find the offenders. Do not eyeball the HTML report.
Run 3-5 times and take the median. A single audit can be noisy. CI must enforce the threshold on every PR.
<video>, <iframe> MUST have explicit width/height or an aspect-ratio container. Unsized media causes CLS.fetchpriority="high" on the LCP image.font-display: swap minimum, optional for non-critical fonts, preload the one critical font, subset to only the characters actually used.<head> synchronously. Defer, lazy-load on first interaction, OR proxy through your own origin to remove a third-party DNS + TLS handshake from the critical path.client:load, ONLY where the interactivity is real. Static routes ship zero JS.<button> for buttons, <a href> for links, <nav> / <main> / <header> / <footer> landmarks, label every form input, alt-text every meaningful image, unique <title> per route.<title>, <meta name="description">, OpenGraph, Twitter cards, structured data (JSON-LD), lang on <html>, viewport, canonical URL.fetchpriority="high" + preconnect to the image CDN is the actual fix.display: none on offscreen content to dodge audits. REJECT. Use content-visibility: auto plus proper lazy mounting. Never lie about the page.localhost and shipping without re-measuring against the deployed URL. REJECT. The CDN, real DNS, and real TLS handshake matter.If the run did not hit 100 in every category, you are NOT done. State so explicitly. Continue iterating.
100 on every Lighthouse category, on a real browser, with full features and full animations intact. Or it is not done.