What are the Core Web Vitals thresholds?
There are three, and web.dev says a page passes when it meets all three at the 75th percentile of page loads, split by mobile and desktop. At the time of writing (2026-10):
- LCP (Largest Contentful Paint): 2.5 seconds or less is good; above 4.0 seconds is poor.
- INP (Interaction to Next Paint): 200 milliseconds or less is good; above 500 milliseconds is poor.
- CLS (Cumulative Layout Shift): 0.1 or less is good; above 0.25 is poor.
LCP is about how fast the main content shows. INP is how quickly the page reacts after a click, tap or key press. CLS is how much the layout jumps around. Next.js gives you good defaults for several of these, but defaults do not pass the test for you. The rest of this post goes through where a typical small business site loses points, in the order we would check.
How do you get a fast LCP image in Next.js?
Start with the largest thing above the fold, usually a hero image or a heading with an image. web.dev's guidance on LCP is blunt: never lazy-load the LCP image, make sure it is discoverable in the initial HTML, and give it high fetch priority. It also says most of the LCP time should go to loading the HTML document and the LCP resource itself.
In Next.js this means:
- Use
next/imagefor that image, withwidthandheight(or a static import). Next.js uses these to reserve space and serves correctly sized, modern formats. - Mark it as important. In Next.js 16 the
priorityprop is deprecated in favor ofpreload, and the docs add that in most casesfetchPriority="high"orloading="eager"is the better choice. Do not usepreloadif different images could be the LCP element on different screen sizes. - Set
sizesso phones do not download desktop-sized files. - Do not hide it in client-only code. If the image appears only after JavaScript runs, the browser finds it late.
Then check your server's response time. The first part of every LCP is the HTML arriving, so a slow server or a chain of redirects costs you before any image problem does.
What should you do about fonts?
Use next/font. The docs say it self-hosts font files, removes the external network requests, and loads fonts with no layout shift. Two common mistakes to avoid:
- adding a Google Fonts
<link>in addition tonext/font, which defeats the point - loading six weights when the design uses two
Fewer font files means less to download before text looks right. A font swap that changes text size is one of the named causes of layout shift in web.dev's CLS guide, so check that the fallback and final font do not differ wildly in size.
How do third-party scripts hurt, and how do you control them?
Chat widgets, tag managers, heatmaps and ad pixels run on the same main thread as your page. They affect INP and often LCP too. The Next.js docs recommend loading third-party scripts only on the pages or layouts that need them, and next/script has strategies:
afterInteractive(the default): load early, after some hydrationlazyOnload: load during browser idle timebeforeInteractive: load before any Next.js code, which is rarely right for marketing toolsworker: experimental, and the docs warn it does not yet work with the App Router
A practical audit, which takes an hour:
- List every script and who asked for it.
- Remove the ones nobody can justify.
- Move the rest to
lazyOnloadwhere the tool still works. - Re-measure.
How do you stop layout shift?
web.dev lists the usual causes: images and videos without dimensions, font swaps, injected content such as ads and embeds, and content that arrives late without reserved space. The fixes follow:
- give every image and video a width and height or an aspect ratio;
next/imagedoes this for you if you give it dimensions - reserve space for embeds, banners and cookie notices before they load
- animate with
transforminstead of properties that change layout - check that late-loading content does not push text down
A cookie banner that pushes the page down when it appears is one of the most common avoidable shifts. Make it overlay or reserve its space.
What do INP and long tasks have to do with it?
INP looks at every click, tap and key press during a visit, and measures the time until the browser can paint the next frame. The usual cause of a bad INP is JavaScript hogging the main thread. web.dev defines a long task as any task over 50 milliseconds, and the fix is to break the work up, use scheduler.yield() where supported, do user-facing work first and defer things like analytics.
For a small business site, the biggest wins are usually boring:
- ship less client-side JavaScript; keep components as server components unless they need interactivity
- avoid heavy libraries for small jobs
- do not run big computations or large list renders inside click handlers
- remove third-party scripts you do not need
Does caching and static rendering matter?
Yes, because the LCP clock starts when the page request starts. A page that is prerendered and served as static HTML skips the work of rendering on every request. The Next.js docs describe route-level controls: you can force a page to be static, or revalidate it after a number of seconds or on demand after an edit. A typical small business site, whose pages change when someone edits content, fits well: prerender, then revalidate when the content changes.
One caution: the Next.js caching docs vary by version and by whether you use the newer Cache Components model. Read the docs for the version you actually run, and test that an edit appears when you expect it to.
How do you measure it properly?
Measure field data first, then use lab tools to find the cause.
- Field data comes from real visitors. web.dev says to prioritize it for decisions. INP in particular cannot be accurately measured in a lab, because a lab cannot predict when users will interact.
- PageSpeed Insights shows both. Its field data comes from the Chrome User Experience Report over a trailing 28 days. If your URL has too little data it falls back to the whole origin, and if that is missing too, you get no field metrics. Its lab data is a Lighthouse test on a simulated device.
- Search Console has a Core Web Vitals report built on the same field data. It covers indexed URLs only, groups similar URLs, separates mobile and desktop, and Google says it is not designed to show the status of one specific URL.
A new or low-traffic site may have no field data for months. In that case use lab runs as a guide, and do not treat one Lighthouse score as the verdict. Run it several times, test on the key pages, and re-check Search Console once data appears.
When this is not for you
- If your site gets very little traffic, field data may not exist yet. Fix the obvious problems (a huge hero image, six widgets) and do not chase the last point of a lab score.
- If your site is built on a platform where you cannot change scripts, images or fonts, most of this does not apply, and a platform change is a bigger discussion.
- Passing Core Web Vitals will not by itself bring traffic. It removes a handicap. Content and relevance still decide most rankings.
- If a page already passes all three at the 75th percentile, leave it alone.
What should you do next?
Run your three most important pages through PageSpeed Insights, write down which metric fails, and fix that one first. If you want a second pair of eyes on a Next.js site, or a site built to pass these thresholds from the start, you can book a free call and we will go through it with you.



