Core Web Vitals & Web Vitals Optimizer
Enter your website's address and analyze it live with the Google PageSpeed Insights API. Depending on which of your LCP, INP, CLS or TTFB metrics comes out weak, instantly copy production-ready code recipes optimized for Next.js 15, React 19 and modern CSS.
Core Web Vitals and Modern Web Performance Optimization Guide
Core Web Vitals, the foundation of Google's Page Experience ranking signals, measure a website's loading speed, interaction responsiveness and visual stability as experienced by real users (CrUX - Chrome User Experience Report). This tool tests your site's LCP, INP, CLS and TTFB metrics live and provides production recipes that deliver a 100/100 Lighthouse score for Next.js 15, React 19 and modern CSS architectures.
1. Core Web Vitals Thresholds and Lighthouse Weights
For a page to count as "Good" in Google's Core Web Vitals assessment, at least 75% of user visits (the 75th percentile) must fall within the green ranges below:
| Metric | Good | Needs Work | Poor | What Does It Measure? |
|---|---|---|---|---|
| LCP (Largest Contentful Paint) | ≤ 2.5 s | 2.5 s – 4.0 s | > 4.0 s | How long it takes for the largest image or text block above the fold to appear on screen. |
| INP (Interaction to Next Paint) | ≤ 200 ms | 200 ms – 500 ms | > 500 ms | The delay before the next frame is painted after a click, tap or keyboard input (replaced FID in March 2024). |
| CLS (Cumulative Layout Shift) | ≤ 0.10 | 0.10 – 0.25 | > 0.25 | Unexpected movement of buttons, banners and text while the page loads. |
| TTFB (Time to First Byte) | ≤ 800 ms | 800 ms – 1800 ms | > 1800 ms | How long the server takes to deliver the first response byte to the browser (DNS, SSL, CDN and server response). |
2. How to Bring LCP (Largest Contentful Paint) Under < 2.5 Seconds
Hero banner images above the fold usually account for 70% of LCP time. A common mistake is accidentally giving the main above-the-fold image loading="lazy":
// A flawless LCP hero image definition with Next.js 15+
import Image from 'next/image'
export function HeroBanner() {
return (
<div className="relative w-full aspect-video max-h-[560px] overflow-hidden rounded-2xl">
<Image
src="/images/hero-showcase.webp"
alt="Core Web Vitals Optimization"
fill
priority // The browser starts downloading it as soon as it reads the HTML (rel="preload")
fetchPriority="high" // Puts it at the highest priority in the browser's network queue
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 80vw, 1200px"
quality={82}
className="object-cover"
/>
</div>
)
}- AVIF & WebP Conversion: Serve your images in modern compression formats to cut file sizes by 50-70%.
- Preconnect: If you use an external CDN or image server, add
<link rel="preconnect" href="https://cdn.site.com" />. - Removing Render-Blocking CSS/JS: Minify the external fonts and stylesheets in the head, or inline critical CSS.
3. INP (Interaction to Next Paint): Why It Replaced FID and How to Improve It
The old metric, First Input Delay (FID), measured only the user's first click on the page. INP (Interaction to Next Paint) tracks every click, key press and mobile tap during the visit and reports the worst interaction delay.
// Preventing main-thread blocking with React 19 useTransition
'use client'
import { useState, useTransition } from 'react'
export function SearchFilter() {
const [inputVal, setInputVal] = useState('')
const [results, setResults] = useState([])
const [isPending, startTransition] = useTransition()
const onSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
const val = e.target.value
// 1. Let the UI respond immediately (input delay = 0ms)
setInputVal(val)
// 2. Run the heavy calculation or DOM filtering in the background
startTransition(() => {
const filtered = calculateHeavyList(val)
setResults(filtered)
})
}
return <input value={inputVal} onChange={onSearch} />
}- Long Animation Frames (LoAF) API: The LoAF API, introduced in Chrome 123, lets you directly detect JavaScript blocking that lasts longer than 50ms.
- Web Workers: Move heavy math, data parsing and crypto functions to a Web Worker.
- Reduce DOM Size: Having more than 1,500 DOM nodes on a single page directly increases paint time.
4. Strategies to Bring CLS (Cumulative Layout Shift) Down to Zero
An ad suddenly opening at the top while the user is reading, or lines shifting when a font loads, is one of the most annoying user experiences. The golden rules for keeping your CLS score at 0.00:
// 1. Zero font shift (Zero Layout Shift) with next/font
import { Inter } from 'next/font/google'
const inter = Inter({
subsets: ['latin'],
display: 'swap',
adjustFontFallback: true, // Automatically matches the fallback font's glyph size to the Google font
})
// 2. Reserving min-height and aspect-ratio for ads and dynamic components
export function AdSlot() {
return (
<div className="w-full min-h-[250px] aspect-video bg-zinc-100 dark:bg-zinc-900 flex items-center justify-center">
{/* The page does not shift down when the ad script loads */}
</div>
)
}5. TTFB (Time to First Byte) & Edge Network Architecture
TTFB reflects your server's performance, database query speed and CDN cache efficiency. With static generation (SSG/ISR) and Edge Middleware in the Next.js App Router, you can bring TTFB down to < 100ms globally:
// app/api/cached-content/route.ts
export const dynamic = 'force-static'
export const revalidate = 3600 // 1-hour Incremental Static Regeneration
export async function GET() {
return Response.json(
{ timestamp: Date.now() },
{
headers: {
'Cache-Control': 'public, s-maxage=3600, stale-while-revalidate=86400',
'CDN-Cache-Control': 'max-age=3600',
},
}
)
}