AI Skill Report Card

Modernizing Web Performance

A-87·Nov 9, 2026·Source: Web
14 / 15

Run a baseline audit before touching any code:

Bash
# Capture current performance baseline npx unlighthouse --site https://example.com --reporter json > baseline.json npx bundlesize npx source-map-explorer 'dist/**/*.js'

Never modernize blind. Baseline metrics (LCP, INP, CLS, TTFB, bundle size, TTI) are the contract you must not break.

Recommendation▾
Add an explicit 'bad outcome' example (e.g., a failed migration) to contrast with the successful ones shown
15 / 15
Progress:
- [ ] Step 1: Establish baseline (Lighthouse/CrUX, bundle analysis, server timing)
- [ ] Step 2: Map architecture (framework version, rendering strategy, data fetching, hosting/CDN)
- [ ] Step 3: Identify bottlenecks (render-blocking JS, hydration cost, waterfalls, cache misses)
- [ ] Step 4: Prioritize upgrades by impact/risk ratio
- [ ] Step 5: Implement incrementally behind feature flags
- [ ] Step 6: Re-measure against baseline after each change
- [ ] Step 7: Codify performance budgets in CI/CD
- [ ] Step 8: Document rollback path for each change

Step 1 — Baseline: Collect field data (CrUX/RUM) if available, not just lab data. Record per-route metrics, not just homepage. Snapshot bundle composition (vendor vs app code, duplicate deps).

Step 2 — Architecture map: Identify: CSR/SSR/SSG/ISR mix, hydration strategy, data-fetching waterfalls, third-party script load, CDN/edge config, current framework major version and migration path to its 2026 equivalent (e.g., React 19 → RSC, SvelteKit → Svelte 5 runes, Next.js App Router, Astro islands).

Step 3 — Bottleneck triage: Classify issues:

  • Network (TTFB, missing edge caching, no HTTP/3)
  • Compute (over-hydration, unnecessary client components, blocking main thread)
  • Payload (oversized JS/images, no code-splitting, unused CSS)
  • Architecture debt (monolithic bundle, no streaming SSR, synchronous data fetching)

Step 4 — Prioritization matrix: Score each fix: (expected metric improvement) ÷ (implementation risk + regression surface). Do cheap/high-impact fixes first (image formats, caching headers, code-splitting) before architectural rewrites (RSC migration, edge function conversion).

Step 5 — Incremental implementation:

  • Convert client components to Server Components route-by-route, not app-wide.
  • Introduce edge functions for specific high-traffic endpoints first.
  • Use feature flags / canary deploys to isolate risk.
  • Keep old code path available until new path is verified in production.

Step 6 — Re-measure: Compare against Step 1 baseline on the same routes/devices/network conditions. Reject any change that regresses Core Web Vitals even if it "feels" more modern.

Step 7 — CI/CD performance budgets:

YAML
# lighthouse-ci config example assertions: largest-contentful-paint: ["error", {maxNumericValue: 2500}] interaction-to-next-paint: ["error", {maxNumericValue: 200}] cumulative-layout-shift: ["error", {maxNumericValue: 0.1}] total-byte-weight: ["error", {maxNumericValue: 1500000}]

Fail the build on budget violation; block merge, not just warn.

Step 8 — Rollback path: Every architectural change must have a feature flag or deploy-level rollback documented before shipping.

Recommendation▾
Include guidance on handling conflicting baseline data between lab and field metrics when they disagree significantly
17 / 20

Example 1: Input: Next.js 13 Pages Router site, LCP 4.2s, fully client-rendered dashboard, no edge caching. Output: Migration plan — move marketing pages to App Router + RSC first (low risk, high win), add edge caching for static assets via CDN headers, defer dashboard migration to phase 2 behind /dashboard-v2 flag. Projected LCP 4.2s → 1.8s on marketing pages; dashboard untouched until RSC data-fetching patterns validated in staging.

Example 2: Input: Svelte 4 SPA with 1.2MB main bundle, INP 340ms due to large reactive stores recalculating on every keystroke. Output: Incrementally port hot-path components to Svelte 5 runes ($state/$derived) to fine-grain reactivity, split bundle via dynamic import() for non-critical routes, add bundlesize CI gate at 400KB. Target INP < 200ms, verified via field RUM before full rollout.

Example 3: Input: Express/EJS server with average TTFB 800ms from a single-region host. Output: Move static/cacheable routes to edge functions (Vercel/Cloudflare Workers), keep stateful logic on origin, add stale-while-revalidate caching. TTFB target <200ms for edge-served routes; origin routes unchanged until load-tested.

Recommendation▾
Consider a brief decision tree or flowchart for the prioritization matrix in Step 4 to make the risk/impact scoring more concrete and actionable
  • Always measure field data (RUM/CrUX), not just synthetic Lighthouse scores — they can diverge significantly.
  • Modernize per-route or per-component, never a full-stack rewrite in one PR.
  • Treat hydration as a cost center: default to server/static rendering, promote to client components only when interactivity requires it.
  • Performance budgets belong in CI, enforced as build-blocking checks, not dashboards nobody reads.
  • Prefer streaming SSR and partial hydration over full rewrites when the existing framework supports it.
  • Document the "why" behind every architectural change — future maintainers need to know the tradeoffs, not just the result.
  • Validate on real devices/networks (mid-tier Android, throttled 4G), not just developer machines.
  • Chasing framework trends (migrating to the newest meta-framework) without profiling data showing it addresses the actual bottleneck.
  • Rewriting the whole app at once — any regression becomes impossible to isolate.
  • Optimizing lab scores (Lighthouse 100) while field metrics (INP, real-user LCP) stay flat or worsen.
  • Adding edge functions/CDN layers without considering cache invalidation and personalization needs — causes stale or leaked data.
  • Removing "legacy" code paths before the new path is validated in production under real traffic.
  • Ignoring third-party scripts (analytics, ads, chat widgets) which are often the actual biggest bottleneck, not the framework.
  • Setting performance budgets as warnings instead of merge-blocking checks — they get ignored within weeks.
0
Grade A-AI Skill Framework
Scorecard
Criteria Breakdown
Quick Start
14/15
Workflow
15/15
Examples
17/20
Completeness
18/20
Format
14/15
Conciseness
13/15