Building Modern Web Apps with Next.js 15
A deep dive into Next.js 15's App Router, React Server Components, and how they change the way we build for the web.
Read the articleActionable strategies for improving Largest Contentful Paint, Interaction to Next Paint, and Cumulative Layout Shift in production applications.

Core Web Vitals help describe loading, responsiveness, and visual stability. They are useful signals for finding friction in a real user journey. A good lab score alone does not establish a good experience for everyone or guarantee search rankings or conversions.
This guide describes a measurement workflow. It does not claim a Lighthouse score for this site or publish unverified client benchmarks.
Good threshold: 2.5 seconds or less
LCP measures how long it takes for the largest visible element (usually a hero image or heading) to render. It's the metric users "feel" most directly.
// Bad: Unoptimized hero image blocks LCP
<img src="/images/hero.png" alt="Hero" />
// Good: Optimized with next/image, priority loading
import Image from 'next/image';
<Image
src="/images/hero.webp"
alt="Hero section showcasing our engineering work"
width={1200}
height={630}
priority
sizes="100vw"
/>
Key strategies:
priority on the LCP element — Tells Next.js to preload the imagesizes prop so the browser downloads the correct variantUse Lighthouse for repeatable lab investigations. Use CrUX, when available, or consent-aware real-user monitoring for field measurements. A synthetic browser run is not equivalent to field data.
Good threshold: 200 milliseconds or less
INP replaced First Input Delay (FID) in March 2024. It measures the latency of all interactions throughout the page's lifecycle, not just the first one.
The biggest INP killers:
// Bad: Heavy computation in click handler
function handleFilter(tag: string) {
const filtered = allPosts
.filter((p) => p.tags.includes(tag))
.sort((a, b) => b.date - a.date)
.map((p) => ({ ...p, excerpt: generateExcerpt(p.content) }));
setFilteredPosts(filtered);
}
// Good: Memoize expensive computations, defer non-critical work
const filteredPosts = useMemo(
() => allPosts.filter((p) => activeTag === 'all' || p.tags.includes(activeTag)),
[allPosts, activeTag],
);
Reducing unnecessary client JavaScript can help. Also inspect long tasks, event handlers, and rendering costs in the interactions people actually use. Measure before choosing an optimization.
Good threshold: 0.1 or less
CLS measures unexpected layout shifts, grouped into session windows; some shifts following user input are excluded. Common causes to investigate include:
// Bad: Image causes layout shift
<img src="/photo.jpg" alt="Team photo" />
// Good: Explicit dimensions prevent shift
import Image from 'next/image';
<Image
src="/photo.jpg"
alt="Team photo"
width={800}
height={600}
className="rounded-lg"
/>
Self-hosting fonts with next/font and choosing suitable fallback metrics can reduce loading and layout problems. With display: swap, fallback text may still appear before the font loads:
import { Poppins, Inter } from 'next/font/google';
const poppins = Poppins({
subsets: ['latin'],
weight: ['600', '700', '800'],
variable: '--font-heading',
display: 'swap',
});
Use this checklist as a starting point, adjusting budgets to the page and its audience:
next/image with explicit width and heightpriority flagloading="lazy" (default in Next.js)"use client" only for interactive componentsdynamic() imports@next/bundle-analyzertransform and opacity only (GPU-composited)display: swap for progressive renderingReport LCP, INP, and CLS from real visits using the web-vitals library, with collection and consent appropriate to the site. Preserve metric names, values, page context, and the sample period; avoid including personal form data or secret URLs.
Evaluate the 75th percentile of visits and separate mobile from desktop. If CrUX has insufficient traffic for a page, report that limitation instead of treating an absent result as a passing score. The Web Vitals overview explains the thresholds and the difference between field and lab tools.
A useful before-and-after report names the page, device profile, connection, software version, test date, sample size, and change being assessed. Keep lab scores separate from field percentiles. Include a trace or stored report so someone else can check the conclusion.
Is your site's performance holding back your search rankings? Schedule a performance audit and we'll identify exactly what's slowing you down and how to fix it.
With your permission, Google Analytics helps us understand which pages people visit. Analytics cookies stay off until you accept. You can change this in Cookie settings.