AI Coding Agents Can Hurt Core Web Vitals: A Frontend Review Checklist

AI coding agents are now good enough to change real production code. That is useful. It is also exactly why they can quietly make a fast frontend slower.

A Claude Code, Codex, Copilot, or Cursor-style agent might solve the ticket perfectly and still hurt Core Web Vitals. It can add a chart library for one small widget. It can turn a server-rendered component into a client component because that was easier. It can lazy-load the hero image. It can add a neat animation that blocks input. The PR passes tests, the UI looks fine, and the regression only shows up later in Lighthouse or field data.

This article is a practical review checklist for AI-generated frontend changes. Use it before merging agent PRs in React, Next.js, Nuxt, Astro, or any JavaScript-heavy app.

The short version

Before merging an AI-generated frontend PR, check:

  1. Dependencies: did the agent add a package for something you could do with CSS or a small helper?
  2. Client JavaScript: did it move code from server/static rendering into the browser?
  3. LCP: did it change the hero image, font loading, route shell, or above-the-fold data?
  4. INP: did it add expensive event handlers, effects, animations, or hydration work?
  5. CLS: did it remove image dimensions, skeleton sizes, reserved ad space, or stable layout containers?
  6. Third parties: did it add analytics, chat, embeds, maps, video, or tag-manager code?
  7. Bundle output: did the first-load JavaScript or route chunk size grow?
  8. Measurements: did the agent provide before/after build and Lighthouse evidence?

If the answer is “I’m not sure” to any of these, do not merge yet. Ask the agent to inspect and report back.

Why AI-generated code can be performance-risky

AI agents optimise for completing the requested task. Unless you explicitly tell them otherwise, they are not necessarily optimising for runtime performance.

A human frontend engineer carries a lot of context in their head:

  • this route is already close to the JavaScript budget
  • this component must stay server-rendered
  • this hero image is the LCP candidate
  • this carousel is intentionally CSS-only
  • this ad slot has reserved height because CLS used to be bad
  • this library was removed last month because it bloated the bundle

An agent may not know any of that. Even when it reads the codebase, it can miss the reason a boring-looking pattern exists.

That is the core risk: AI agents often produce plausible code without understanding the performance scars behind the current code.

1. Check new dependencies first

Start every AI PR review with the package diff.

Look for changes in:

  • package.json
  • package-lock.json, pnpm-lock.yaml, or yarn.lock
  • framework config files
  • route-level imports

Common agent behaviour:

+ import { motion } from 'framer-motion'
+ import dayjs from 'dayjs'
+ import { LineChart } from 'recharts'
+ import debounce from 'lodash/debounce'

Sometimes that is fine. Often it is not.

A single agent-generated feature can pull in:

  • animation libraries for a hover effect
  • chart libraries for a simple sparkline
  • date libraries for formatting one date
  • icon packs for three icons
  • markdown/rendering libraries for static copy
  • validation libraries for a tiny form

For Next.js and React apps, compare the output from your production build. If you use Next.js, the First Load JS number is the first thing to check. See the Next.js build output guide if that table is confusing.

Useful review prompt:

Review this PR for new dependencies and bundle-size risk.
For each new package, explain:
1. where it is imported,
2. whether it affects initial load or only a lazy route,
3. whether native browser APIs, CSS, or existing project utilities could replace it,
4. the expected impact on first-load JavaScript.
Do not change code yet. Return a short risk table.

2. Check whether server-rendered code became client JavaScript

This is one of the easiest ways for an AI agent to make a modern app slower.

In Next.js App Router, watch for added "use client" directives. In Astro, watch for extra client:load islands. In Nuxt, watch for browser-only components, large composables, or plugins that now run on every page.

The agent might add client-side state because it is the fastest way to make a component interactive:

'use client'

import { useState } from 'react'

export function PricingCards({ plans }) {
  const [selected, setSelected] = useState(plans[0].id)
  // ...
}

That may be acceptable for a genuinely interactive component. It is not acceptable if the whole page became a client component just to toggle one small detail.

Review questions:

  • Did a parent layout become a client component?
  • Did a server component start importing client-only code?
  • Did static content become hydrated JavaScript?
  • Did an Astro island change from client:visible or client:idle to client:load?
  • Did a Nuxt plugin move from route-specific usage to global usage?

Related guides:

Useful review prompt:

Check whether this change increases client-side JavaScript.
Look for new "use client" boundaries, hydrated islands, browser-only plugins, or components that now run on every page.
Suggest the smallest change that keeps static/server-rendered code out of the client bundle.

3. Protect the LCP element

Largest Contentful Paint is often controlled by one obvious thing: the hero image, heading block, or top-of-page content.

AI agents commonly break LCP by:

  • lazy-loading the hero image
  • removing image priority hints
  • changing image dimensions
  • adding a client-rendered hero carousel
  • moving critical content behind a loading state
  • adding a font or animation that delays above-the-fold text
  • fetching hero content on the client instead of rendering it in HTML

A visually nicer hero can be a worse hero.

Bad sign:

<Image
  src={hero.src}
  alt={hero.alt}
  loading="lazy"
  className="rounded-3xl"
/>

If that image is the LCP candidate, lazy loading is probably wrong. Give it stable dimensions, appropriate sizes, and priority/preload treatment depending on the framework.

Useful review prompt:

Identify the likely LCP element on this route before and after the change.
Check whether the PR changed image loading, dimensions, priority/preload, font loading, client rendering, or above-the-fold data fetching.
If there is LCP risk, propose a minimal fix.

4. Watch INP: effects, handlers, and generated interactivity

Interaction to Next Paint gets worse when the main thread is busy after a user interacts.

AI-generated UI often adds more interactivity than the ticket really needed:

  • search-as-you-type without debouncing
  • filters that recompute a large list on every keypress
  • animations triggered on every scroll event
  • charts that re-render on hover
  • global event listeners without cleanup
  • useEffect chains that update state repeatedly
  • client-side sorting/filtering that should be server-side or precomputed

Look for code like this:

<input onChange={(event) => setQuery(event.target.value)} />

const filtered = items.filter(item =>
  item.title.toLowerCase().includes(query.toLowerCase())
)

That is fine for 20 items. It is not fine for 5,000 items plus expensive rendering.

Ask:

  • How many DOM nodes can this render?
  • Does it run on every keystroke?
  • Can it debounce or defer work?
  • Can it virtualize large lists?
  • Can it move expensive calculations outside render?
  • Does it need JavaScript at all?

Useful review prompt:

Review this PR for INP risk.
Focus on event handlers, effects, large renders, animations, scroll listeners, filters, search inputs, and client-side data processing.
Return the top 5 likely main-thread risks and how to measure each one.

5. Do not let generated UI create CLS

Cumulative Layout Shift regressions are easy to miss in code review because the page often looks fine after it settles.

AI agents can create CLS by:

  • removing width and height from images
  • adding late-loading banners above content
  • inserting ads without reserved slots
  • using skeletons that do not match final dimensions
  • changing font loading without fallbacks
  • rendering a different mobile layout after hydration
  • adding expandable sections above the main content

CLS review is mostly about reservation. If something loads late, it needs space before it arrives.

Useful review prompt:

Review this UI change for CLS risk.
Check images, embeds, ads, banners, skeletons, fonts, mobile layout changes, and hydration-only content.
List anything that appears after initial render and whether its space is reserved.

6. Be suspicious of “small” third-party scripts

Agents often reach for third-party services because they solve the problem quickly:

  • analytics snippets
  • chat widgets
  • calendars
  • maps
  • embeds
  • A/B testing tools
  • social pixels
  • video players

Each script can affect LCP, INP, or both. Some also shift layout.

If the agent adds a third party, require a short justification:

  • What does it do?
  • Does it load on every route?
  • Can it be delayed until user intent?
  • Can it load after consent or interaction?
  • Can a server-side or static alternative work?
  • Is it isolated from critical rendering?

Use the third-party scripts Core Web Vitals guide as the review companion.

7. Make the agent produce evidence, not confidence

A good AI coding agent can also run checks. Use that.

For a frontend PR, ask for:

  • production build output
  • route bundle diff
  • dependency diff
  • Lighthouse result before/after
  • screenshots of the changed route
  • list of changed client/server boundaries
  • suspected effects on LCP, INP, and CLS

Do not accept “this should improve performance” as evidence. Ask for numbers.

A solid agent report looks like this:

Performance review:
- New dependencies: none
- First Load JS: /pricing increased from 112 kB to 118 kB (+6 kB)
- LCP candidate: hero heading, unchanged
- INP risk: pricing toggle now re-renders 18 cards, acceptable but should be tested on mobile
- CLS risk: FAQ accordion reserves no extra space, but content expands only after user interaction
- Lighthouse mobile: Performance 91 -> 90, no major regression
- Recommendation: safe to merge, monitor INP in field data

That is much more useful than a generic “tests passed”.

8. Add performance guardrails to your agent instructions

If you use Claude Code, Codex, or another repo-aware agent, put performance rules in the project instructions file.

Example:

Frontend performance guardrails:
- Do not add new runtime dependencies without explaining bundle impact.
- Prefer server-rendered/static components unless interactivity is required.
- Do not add "use client" to route/layout components without justification.
- Preserve image width/height, sizes, priority/preload, and lazy-loading intent.
- Keep the LCP element renderable without client-side JavaScript where possible.
- Avoid scroll listeners, large re-renders, and unbounded client-side filtering.
- Reserve space for images, ads, embeds, banners, and skeleton states.
- Run the production build and report bundle/output changes for frontend PRs.
- For performance-sensitive routes, include Lighthouse or WebPageTest before/after notes.
- Never deploy automatically; open a PR with risks and verification results.

This is boring. Boring is good. Agents are much safer when the rules are explicit.

9. Use route budgets for AI-generated changes

A simple route budget stops performance review from becoming subjective.

For example:

  • marketing pages: no new client JavaScript unless necessary
  • blog pages: static HTML preferred, no interactive widgets by default
  • app dashboard pages: route chunk increase over 20 kB needs justification
  • checkout/contact flows: no third-party scripts added without approval
  • image-heavy pages: LCP image must keep dimensions and priority handling

You do not need a perfect budget. You need enough friction that an agent cannot accidentally add 90 kB for a cosmetic feature.

10. The AI frontend PR checklist

Copy this into your PR template or agent review prompt.

Dependencies

  • Did the PR add new runtime dependencies?
  • Are they used on initial load or only lazy routes?
  • Is there a smaller/native/CSS alternative?
  • Did the production bundle size change?

Rendering boundaries

  • Did any server/static component become client-rendered?
  • Were new "use client", hydrated islands, or global plugins added?
  • Can interactivity be pushed lower in the component tree?

LCP

  • Is the LCP element still obvious?
  • Did hero image loading, priority, dimensions, or sizes change?
  • Did above-the-fold content move behind client fetch or loading states?
  • Did fonts or animations delay initial text/image rendering?

INP

  • Were expensive event handlers added?
  • Do filters/search/sorting run on every keystroke?
  • Are effects causing repeated state updates?
  • Are animations or scroll listeners doing main-thread work?

CLS

  • Do images, ads, embeds, and skeletons reserve space?
  • Did banners, cookie prompts, or alerts appear above content?
  • Does the mobile layout match before and after hydration?

Third parties

  • Were analytics, chat, maps, embeds, pixels, or tag scripts added?
  • Do they load only when needed?
  • Can they be delayed, consent-gated, or replaced?

Evidence

  • Production build ran successfully.
  • Bundle/build output was compared.
  • Lighthouse or lab test was run for affected routes.
  • The agent explained performance risks in plain English.

Example prompt: make the agent review its own work

Use this after an agent finishes a frontend task:

Before I review this PR, do a frontend performance self-review.

Check the diff for:
- new dependencies
- increased client-side JavaScript
- changed server/client boundaries
- LCP image or above-the-fold changes
- INP risks from handlers/effects/renders
- CLS risks from images, ads, embeds, skeletons, and late content
- third-party scripts

Run the production build. If the framework prints bundle or route-size output, summarize the relevant changes.
Do not make more changes unless you find a clear regression. Return:
1. likely LCP impact,
2. likely INP impact,
3. likely CLS impact,
4. bundle/dependency impact,
5. whether this is safe to merge.

Example prompt: ask the agent to fix a regression

If Lighthouse or field data already caught a regression:

This PR appears to have worsened Core Web Vitals.
Investigate without guessing.

Route: <URL>
Metric affected: <LCP / INP / CLS>
Before: <number>
After: <number>
Relevant changed files: <files>

Find the most likely cause in the diff. Prioritize:
- LCP image/rendering/data changes for LCP
- event handlers/effects/main-thread work for INP
- missing dimensions/late content/reserved space for CLS

Propose the smallest safe fix, explain the tradeoff, then implement it.
Run the build and summarize before/after evidence.

What this means for real teams

AI coding agents are not bad for performance. Unreviewed AI coding agents are bad for performance.

The best workflow is not “never let agents touch frontend code”. That throws away too much productivity. The better workflow is:

  1. let the agent draft the change
  2. force it to produce performance evidence
  3. review the risky parts humans are good at spotting
  4. measure before merging
  5. keep deploy approval separate from code generation

That is the same pattern Google DeepMind and other AI teams are talking about at a larger scale: capable agents need boundaries, permissions, monitoring, and review. For frontend teams, the practical version is simpler. Keep your agent out of production deploys, make it explain bundle/runtime changes, and do not merge UI code until LCP, INP, and CLS risks are checked.

If you want a quick external check, run the changed route through PageSpeedFix after deploying to a preview URL. Use the output to ask the agent for targeted fixes instead of generic performance advice.

Final recommendation

For every AI-generated frontend PR, require one extra section:

Core Web Vitals risk:
- LCP:
- INP:
- CLS:
- Bundle impact:
- Third-party impact:
- Verification run:

That small ritual catches the most common agent mistakes: too much JavaScript, unstable layout, slow interactions, and unmeasured “improvements”.

AI agents can make your frontend faster. But only if you treat performance as a requirement, not a nice-to-have after the PR is already merged.

D
Declan

Software engineer in Melbourne. Writes guides at PageSpeedFix and builds web performance tools. More at dekk.dev.