6 November 2026 · 12 min read · BlitzHash · Performance
Core Web Vitals for Next.js: the first three fixes for vibe-coded apps
Short answer: for Core Web Vitals on a Next.js app that AI helped you build, fix three things first — identify the real Largest Contentful Paint (LCP) element and load it early with next/image (never lazy-load the hero), reserve space for every image and font so Cumulative Layout Shift (CLS) stays low, and shrink the JavaScript that runs on every click so Interaction to Next Paint (INP) stays under 200 ms. Google's thresholds, measured at the 75th percentile of real visits, are LCP under 2.5 seconds, INP under 200 milliseconds, and CLS under 0.1. If your app already feels sluggish for customers, our launch-ready check reviews speed alongside security, privacy, scaling and the bill.
This guide is for founders who shipped with Lovable, Bolt, Cursor, Replit or v0 onto a Next.js + Vercel stack, and now see "Needs improvement" in Search Console or PageSpeed Insights — or just feel the page jump and lag when people tap buttons.
What Core Web Vitals actually measure
Core Web Vitals are Google's three field metrics for real user experience. According to web.dev's Web Vitals overview (updated October 31, 2024), the stable set is:
- LCP (Largest Contentful Paint): how quickly the main content appears. Good is 2.5 seconds or less.
- INP (Interaction to Next Paint): how quickly the page responds after a tap, click or keypress. Good is 200 milliseconds or less. INP replaced First Input Delay as a Core Web Vital in 2024.
- CLS (Cumulative Layout Shift): how much the layout jumps while things load. Good is 0.1 or less.
You pass when all three hit those targets for at least 75% of visits, split by mobile and desktop. Lab tools (Lighthouse on your laptop) are useful for debugging. Field data (Chrome User Experience Report in PageSpeed Insights or Search Console) is what Google uses for the report that matters.
Why vibe-coded Next.js apps struggle with Core Web Vitals
AI builders are great at screens. They are less careful about what the browser has to download and run before a person can read or click. Patterns we see again and again:
1. A hero image added as a plain ` without width and height, or with loading="lazy" on the thing above the fold. 2. A page marked "use client"` at the top so the whole tree ships to the browser, including charts and editors nobody needs on first paint. 3. Cookie banners, chat widgets and analytics scripts that push content down after paint. 4. Fonts loaded from a third-party CSS file with no size-adjust, so text reflows when the webfont arrives. 5. Client-side data fetching for the main heading, so LCP waits on JavaScript instead of arriving in the HTML.
None of that means you have to rewrite the product. It means you run a short triage, then apply the three fixes below.
What we measured on our own Next.js site
Before giving advice, we inspected blitzhash.com (Next.js on Vercel) with curl on November 6, 2026. This is HTML and header data, not a lab Lighthouse score — Google's public PageSpeed API was rate-limited from this environment that morning — but it shows the same signals founders can check without a performance engineer.
- The homepage HTML is about 117 KB. The
/checkmoney page is about 71 KB. - From our measurement region, Time to First Byte (TTFB) for the homepage was about 0.86 seconds end-to-end (
curltime_starttransfer), with the response markedx-vercel-cache: HITandx-nextjs-prerender: 1. - The homepage has 16 `` tags. Every one already has both
widthandheightattributes — the CLS-friendly pattern Next.js documents fornext/image. - 15 of 16 images use
loading="lazy". The logo usesloading="eager"withfetchPriority="low"andsizes="64px". That is the right instinct for a small brand mark; the LCP element is usually a hero image or a large heading, not the logo. - Response
Linkheaders preload two self-hostedwoff2fonts (about 23 KB and 29 KB), which matches thenext/fontpattern of shipping fonts from your own origin instead of waiting on Google Fonts CSS. - The Content-Security-Policy allows
https://vitals.vercel-insights.com, so the project is already wired to send vitals somewhere — useful when you adduseReportWebVitalslater. - There are 47 `` opening tags in the homepage HTML (including framework chunks). That is normal for a modern Next app, and it is also why INP work starts with "ship less client JavaScript," not with micro-optimizing one button.
Use those numbers as a template for your own site: count images with dimensions, find anything above the fold that is still lazy, check whether fonts are preloaded from your origin, and note TTFB before you rewrite components.
Core Web Vitals for Next.js: the 20-minute triage
Do this once on your live production URL (not only on localhost). Write the numbers down so you can see whether the three fixes helped.
Step 1: Open PageSpeed Insights on your real URL
Go to PageSpeed Insights, paste your production URL, and run it for mobile. If "Discover what your real users are experiencing" shows data, trust that section first. Lab scores below it are a diagnosis aid, not the final grade. Search Console's Core Web Vitals report groups URLs the same way once you have enough traffic.
Step 2: Name the LCP element
In Chrome, open DevTools → Performance, start recording, reload, stop, and look for the LCP marker. Or in PageSpeed Insights, open the Largest Contentful Paint element diagnostic. Write down whether it is:
- a hero image,
- a large heading in a webfont, or
- a background image set in CSS (hardest, because the browser cannot see it in the HTML).
web.dev's Optimize LCP guide (updated March 31, 2025) is blunt: most of the win comes from discovering that resource early and giving it priority — not from compressing it a second time after JavaScript has already delayed it.
Step 3: Watch one interaction for INP
On a mid-range phone or Chrome's CPU throttling, open your heaviest screen (dashboard, editor, pricing calculator). Tap the primary button. If the UI freezes before paint, you have an INP problem even if the page "loads fast." Lighthouse cannot fully measure INP without a user; Total Blocking Time in the lab is only a proxy.
Step 4: Film the first two seconds for CLS
Record the first load with your phone camera or DevTools. If a cookie banner, announcement bar or late image pushes the heading down, that is CLS. Next.js's image component reserves space when width and height are set; late-injected UI often does not.
Fix 1: Get LCP under 2.5 seconds
Use next/image for the real LCP image — and never lazy-load it
Next.js documents that the Image component provides size optimization, visual stability and lazy loading by default. For the one above-the-fold LCP image, override the defaults:
import Image from 'next/image'
import hero from './hero.png'
export function Hero() {
return (
)
}priority tells Next to preload the image. Do not put priority on every image — web.dev notes that fetch-priority hints stop helping when everything is high priority. Remote images need explicit width and height (or fill inside a sized parent) because Next cannot read remote dimensions at build time.
AI-builder prompt you can paste: "Find the largest above-the-fold image on the home page. Convert it to next/image with the priority prop, correct width and height, and a sizes attribute that matches how wide it actually displays on phones. Remove loading=lazy from that image only."
Prefer server-rendered content for the LCP text
If your LCP element is a heading that appears only after a client fetch, move that data into a Server Component so the HTML arrives with the text. Client-side rendering of the main headline is one of the classic LCP delays in AI-generated apps.
Keep fonts on your origin
Use next/font so fonts self-host and preload. Our homepage's Link preload headers for two woff2 files are exactly that pattern. Avoid a render-blocking Google Fonts CSS chain when the LCP element is text.
Watch TTFB
If TTFB alone is already near 2.5 seconds, no frontend trick will save LCP. Fix redirects, region mismatch, and uncached origin work first. Our own cached homepage TTFB under a second is the shape you want; a cold origin with many redirects is not.
Fix 2: Keep CLS under 0.1
Always set dimensions (or use next/image)
Unset images start at height 0 and shove content down when they load. On our homepage, all 16 images already declare width and height — keep that habit when you add new screenshots from Lovable or Bolt exports. For remote URLs, pass width and height manually.
Reserve space for banners and embeds
Cookie notices, Calendly embeds, chat bubbles and A/B banners should either overlay content or sit in a reserved box with a fixed min-height. Never insert a tall bar above content the user is already reading unless they clicked something.
Match font metrics
next/font can adjust fallback metrics so text does not jump when the webfont swaps in. If you still load fonts by hand, set font-display: swap and avoid late @font-face rules discovered only after CSS arrives.
Skeletons that match final height
Loading skeletons that are shorter than the real card cause a second shift when data arrives. Size the placeholder like the finished block.
Fix 3: Get INP under 200 ms
INP is a main-thread problem. A site can paint the hero quickly and still fail when someone taps "Generate" or opens a filter.
Push "use client" to the leaves
Default to Server Components. Put "use client" only on the interactive leaf (the button, the form, the chart), not on the whole page. A page that starts with "use client" ships its entire tree for hydration.
Lazy-load heavy widgets
Charts, rich-text editors, PDF viewers and big date pickers belong behind next/dynamic so they load when needed:
import dynamic from 'next/dynamic'
const HeavyChart = dynamic(() => import('./HeavyChart'), {
ssr: false,
loading: () => Loading chart…,
})Give instant feedback on expensive updates
Use useTransition for state that re-renders a big list so the press paints immediately while the heavy work continues. Break long loops into chunks, or move parsing to a worker.
Audit third-party scripts
Load analytics, chat and heatmaps with next/script and strategy="afterInteractive" or lazyOnload. Turn one off in a test deploy and re-check INP — founders are often surprised which widget owns the main thread.
AI-builder prompt you can paste: "List every file with 'use client' at the top. Move that directive to the smallest child that needs hooks or browser APIs. Dynamic-import any chart, editor or map that is not visible on first paint."
Downloadable-free checklist (print or copy)
Mark each item ☐ Pass / ☐ Fail / ☐ Not sure. "Not sure" counts as fail until you check.
Measure
- ☐ PageSpeed Insights (or Search Console) run on the production URL, mobile view saved
- ☐ LCP element identified (image / heading / CSS background)
- ☐ One primary tap timed on a phone or with CPU throttle
- ☐ First-load recording checked for layout jumps
LCP
- ☐ Above-the-fold LCP image uses
next/imagewithpriority(not lazy) - ☐
sizesmatches real display width on phones - ☐ Main heading HTML arrives from the server, not a client fetch
- ☐ Fonts self-hosted or preloaded from your origin
- ☐ TTFB checked; no chain of marketing redirects into the app
CLS
- ☐ Every image has width and height (or
fillin a sized parent) - ☐ Cookie / announce banners reserved or overlaid
- ☐ Embeds (calendars, videos) have a fixed min-height box
- ☐ Skeleton loaders match final card height
INP
- ☐
"use client"only on interactive leaves - ☐ Heavy widgets behind
next/dynamic - ☐ Primary buttons show immediate feedback on press
- ☐ Third-party scripts deferred; unused ones removed
Ship
- ☐ Re-run PageSpeed Insights after the three fixes
- ☐ Note field data in a week (CrUX lags) before declaring victory
How this ties to launch readiness
Speed is one lane of "ready for customers." A fast page that leaks data still fails. Pair this Core Web Vitals work with:
- the 12-check production scorecard for auth, backups and spend caps,
- the Edge Requests / CDN Requests audit when the Vercel usage chart is climbing,
- and the free self-check when you want a traffic-light read on security, privacy, speed, scaling, costs and backups.
For day-to-day engineering habits (reviews, CI, production gates), our open Senior Engineer Skills repo is a Cursor-oriented checklist you can drop into an AI coding workflow — useful when the same agent that built the UI is also the one that should stop shipping layout-shift heroes.
FAQ
Do Core Web Vitals affect Google ranking for my SaaS landing page?
Google has said Core Web Vitals are part of its page experience signals. They are not the only ranking factor, and a useful product still needs links and intent match. Treat a "Poor" report as a customer-experience bug first; search is a side benefit of fixing it.
Lab score is green but Search Console says Needs improvement. Which do I trust?
Trust the field data. Lab tests run on a fixed device and network. Your real visitors use mid-range phones on flaky LTE. Optimize for the 75th percentile in CrUX / Search Console, then use Lighthouse to find the cause.
My app is mostly a logged-in dashboard. Do Core Web Vitals still matter?
Yes for marketing and signup pages that Google indexes, and yes for retention on the dashboard — INP especially. CrUX mainly reflects public URLs with enough Chrome traffic; instrument useReportWebVitals from next/web-vitals for private screens so you still see LCP/INP/CLS from real sessions.
Will moving off Vercel fix Core Web Vitals?
Usually no. Hosting changes TTFB and edge distance. Most vibe-coded failures we see are image discovery, client JavaScript weight and late banners — the same on any host. Fix those first; then compare bills with a Vercel bill review if cost is the separate problem.
Book a free technical assessment
If you want a senior pass over speed, security and launch readiness together — not a generic Lighthouse PDF — book a free technical assessment or start with the launch-ready check. Bring your production URL and, if you have it, the PageSpeed Insights link. We will tell you which of LCP, INP or CLS is actually costing you customers, and what to change first.
Sources
- Web Vitals
- Optimize Largest Contentful Paint
- Optimize Interaction to Next Paint
- The most effective ways to improve Core Web Vitals
- Next.js Image Optimization
- useReportWebVitals
- Vercel Academy: Core Web Vitals + Measurement
