Home Benchmarks Learn Tools News
Learn · Guides · Performance

AI for Performance Optimization.

Agents won't make your app fast on vibes — but feed them the right inputs (RUM, Lighthouse JSON, bundle report) and they'll outperform a human pass at finding regressions. Prompts that work for LCP, INP, CLS, and a builder that hands you the right one for your worst metric.

SPONSOR

AppSignal — RUM is the ground truth. AppSignal's frontend monitoring gives the agent the real p75 numbers — not Lighthouse fairy tales.

↗
On this page
  1. The metrics that matter
  2. Data in, fixes out
  3. LCP: the prompt that works
  4. INP: the harder one
  5. CLS: usually trivial, usually overlooked
  6. The unnecessary-client-component hunt
  7. Prompt builder: build the prompt for your worst metric
  8. Pitfalls
CH 01

The metrics that matter.

Metric What it measures Good (p75) Poor (p75)
LCP Time to render the largest visible element. ≤ 2.5 s > 4.0 s
INP Worst interaction-to-next-paint delay across the session. Replaced FID in March 2024. ≤ 200 ms > 500 ms
CLS Cumulative layout shift — how much the page jumps around. ≤ 0.1 > 0.25
TTFB Time to first byte. Floors LCP — not measured directly by CWV but worth tracking. ≤ 0.8 s > 1.8 s

Google scores you on the p75 of real user data, not your dev machine. "Fast on localhost" is a vanity metric. The agent needs your field data to do anything useful — either CrUX (free, lagging by 28 days) or your own RUM (live, what you actually want).

CH 02

Data in, fixes out.

The single biggest difference between agents that fix performance and agents that hand-wave is the inputs in the prompt. The minimum kit:

  • Lighthouse JSON for the route, generated locally or from PageSpeed Insights. Save as lighthouse.json; the agent can read it.
  • Bundle report. For Next.js, @next/bundle-analyzer's JSON output. For Vite, rollup-plugin-visualizer with json: true. For everything else, esbuild --metafile.
  • RUM snapshot. P75 LCP / INP / CLS, ideally broken down by route and device class. CSV is fine.
  • The route tree. tree app -L 4 output for Next or your equivalent. Without this, the agent doesn't know what's a server component and what's not.

Drop these in a perf/ folder in the repo (gitignored), reference them in the prompt. The agent will read them. Without them, you're getting generic advice.

CH 03

LCP: the prompt that works.

LCP is the most fixable metric. The agent's success rate is high if you point it at the right inputs and the right culprits.

LCP prompt
The route /products/[slug] has p75 LCP of 3.8s on mobile (target: <2.5s).

Inputs:
- perf/lighthouse-product.json
- perf/bundle-report.json
- The route file: app/products/[slug]/page.tsx

Find the LCP element. Check, in order:
1. Is it an <img>? Does it have width/height, priority, and a sized srcset?
2. Is it blocked by a render-blocking request? (CSS or sync JS)
3. Is it inside a client component that gates on JS? Promote to server.
4. Is there a font swap that delays it? Add font-display: swap and preload.
5. Are we waiting on a third-party script? Defer or remove.

Propose the smallest diff that wins. Do not refactor. Show before/after of the suspected element only.

Note what the prompt does not do: it doesn't ask "make LCP better." It hands the agent a fixed checklist in priority order. The model is good at executing a checklist against real data; it's poor at picking the right priority unprompted.

CH 04

INP: the harder one.

INP is harder because the cause is almost always main-thread work, and main-thread work is harder to inspect statically. The trick is to pair the agent with the right trace.

  • Capture a real interaction trace. Open DevTools Performance, record, do the slow interaction, save the JSON profile (Chrome > Performance > Save profile).
  • Hand it to the agent. "Read perf/interaction-trace.json. Find the longest task on the main thread between the user input and the next paint. Identify the function and propose a fix."
  • Common culprits. Synchronous state updates that cascade, layout thrashing in scroll handlers, big chunks of JSON.parse, hydration of huge client trees, third-party tag managers.
INP prompt
P75 INP on /dashboard is 540ms (poor; target <200ms).

Inputs:
- perf/interaction-trace.json  (Chrome DevTools profile, recorded during the search-typing interaction)
- The component: app/dashboard/SearchInput.tsx

Find the longest task on the main thread between the user input and the next paint. Likely candidates:
1. A synchronous setState cascade that re-renders the whole list on each keystroke.
2. A useEffect that runs a heavy computation per change.
3. A controlled input with no debounce or transition.

Propose a fix using useDeferredValue, useTransition, or a debounce — whichever matches the actual cause. Do not introduce a new state manager.
CH 05

CLS: usually trivial, usually overlooked.

90% of CLS comes from four causes. An agent fixes any of them in one PR if you ask the right question.

  • Images without explicit dimensions. width and height attributes, or aspect-ratio.
  • Web fonts swapping in. font-display: optional for marketing pages, swap with a metrics-matched fallback for app shells.
  • Banners / cookie consent / sponsors injected after layout. Reserve the space; never let content push down.
  • Embeds (YouTube, tweets, ads) without a placeholder. Wrap in a fixed-aspect container.
CLS prompt
P75 CLS on /article/[slug] is 0.18 (poor).

Audit these surfaces, in order:
1. <img> / <Image> tags missing width/height or aspect-ratio.
2. @font-face declarations without font-display or with mismatched x-height fallback.
3. Late-injected DOM nodes (analytics, consent, sponsor slot) above the fold.
4. Embed wrappers with no reserved space.

Propose the minimum changes that bring CLS under 0.1. Do not migrate to next/image; we are on plain <img>.
CH 06

The unnecessary-client-component hunt.

The single highest-impact Next.js / React Server Components prompt in 2026. Most apps that migrated to App Router have a few dozen accidental 'use client' at the top of components that don't need it — each one pulls its whole subtree into the client bundle.

The hunt
Scan app/**/*.tsx for files that start with 'use client' but do NOT use any of:
- React hooks (useState, useEffect, useRef, useReducer, useMemo, useCallback, useContext, useId)
- Event handlers (onClick, onChange, onSubmit, onInput, etc.)
- Browser APIs (window, document, localStorage, navigator)
- Third-party hooks that require client (useChat, useRouter from next/navigation, etc.)

For each match:
1. List the file path.
2. Show the imports — confirm none are client-only.
3. Propose removing 'use client'.
4. Identify which children of this component, if any, also become server.

Then estimate the client-bundle reduction in KB using perf/bundle-report.json. Order results by reduction, descending.
"It worked, so I removed all of them"

Some components legitimately need the boundary even when they don't directly use a hook — e.g., a server component that imports a third-party library that breaks under SSR. Removing every one will introduce hydration errors. Always run the build and a smoke test after the change; let the build tell you which ones were load-bearing.

PROMPT BUILDER

Build the prompt for your worst metric.

Drop in your p75 numbers and the route; the tool picks the metric to fix first and gives you the prompt to hand the agent. The thresholds are Google's Core Web Vitals — the prompt is the work.

Prompt builder p75 field data · In-browser only
Priority —
  • LCP —
  • INP —
  • CLS —
Adjust the sliders to see priority.
Generated prompt (paste into your agent)
Pick your failing metric to see a prompt.

Fix the worst metric first. Don't spread effort across all three. A 30% LCP win on a poor-LCP route moves more p75 users into "good" than 5% improvements on all three combined.

PITFALLS

Pitfalls.

Optimizing Lighthouse instead of users

Lighthouse runs once, on a simulated mid-tier device, in a clean profile. Your users run a thousand times, on real devices, with extensions and tabs and a cold cache. A 5-point Lighthouse jump that doesn't move RUM is a vanity win.

"Lazy-load everything"

Lazy-loading the LCP element is how you go from "slow" to "broken." Agents will happily do this if you ask them to "reduce bundle size" without constraints. Be specific: "lazy-load only components below the fold; preserve everything in the initial viewport."

Migrating frameworks "for performance"

The agent will, if asked, propose a Remix → Next migration on perf grounds. Don't. Migrations are 100× the work of fixing the actual bottleneck, and the new framework has its own surprises. Fix the metric in the framework you're already on.

No regression test on the metric

Without Lighthouse-CI (or Vercel Speed Insights budget alerts, or your equivalent), your win will silently regress in three sprints when someone adds a chart library. The agent can write the assertion; it can't write the discipline.

What to read next.

  • Guide · 16 Observability for AI Features The backend half of the perf story — LLM-call latency and budget.
  • Guide · 13 Prompting for UI Code Prevent the perf regressions you're now fixing.
  • Guide · 09 Testing AI-Written Code Performance is a contract too — pin it with a test.
Changelog
  • 2026-05-26Initial publish.
STATUS ● BUILDING THE FUTURE
MISSION LLM RESOURCES
VERSION BETA 3.0

BUILD WITH AI. SHIP WITH CONFIDENCE.

@WEBDEVELOPERHQ ↗
TERMS / PRIVACY
FRIENDS
Authentic Jobs
Authentic Jobs ↗
Web Reference
Web Reference ↗
Ready.dev
Ready.dev ↗
Design.dev
Design.dev ↗
© 2026 WEB DEVELOPER / ALL RIGHTS RESERVED