← All Articles
Engineering9 min read

Core Web Vitals in 2025: How We Achieve Green Scores on Complex Apps

October 28, 20249 min read

Core Web Vitals measure real user experience: loading speed (LCP), interactivity (INP), and visual stability (CLS). Poor scores hurt both users and search ranking. Here's how we systematically improve them.

LCP — Largest Contentful Paint (target: under 2.5s)

LCP measures when the largest visible element renders. It's almost always a hero image or heading. The optimisation path is predictable: preload the LCP element with <link rel="preload">. Serve images in WebP/AVIF format. Size images correctly — don't serve a 2000px image in a 400px container. Use priority prop on Next.js Image for the LCP image. Eliminate render-blocking resources that delay the LCP element.

The most common LCP killer we find in audits: a hero section that imports a large JavaScript library before rendering. Move it to the client boundary, render the hero server-side.

INP — Interaction to Next Paint (target: under 200ms)

INP replaced FID as the interactivity metric. It measures the delay between user input and the next paint — across all interactions during the page lifecycle, not just the first. Long JavaScript tasks on the main thread are the primary cause. Fix: break long tasks with scheduler.yield(). Move heavy computation to a Web Worker. Defer non-critical JavaScript. Virtualize long lists.

CLS — Cumulative Layout Shift (target: under 0.1)

Layout shifts happen when elements move after the page loads — usually because images have no size attributes, ads inject content above existing content, or web fonts cause text reflow. Fix: always set explicit width and height on images. Reserve space for dynamic content. Use font-display: optional to prevent FOIT. Test with slow network throttling to catch shifts that happen during load.

The optimisation process

Measure with WebPageTest (real browser, real network) — not just Lighthouse. Identify the worst-performing pages. Profile with Chrome DevTools Performance tab. Fix the biggest bottleneck. Measure again. Repeat. Don't optimise based on assumptions — every fix should be validated with measurement.

Next.js specific wins

Enable the new Next.js Image component for automatic WebP conversion and lazy loading. Use Server Components to eliminate client-side data fetching waterfalls. Use next/font to self-host fonts and eliminate cross-origin font requests. Enable Partial Prerendering (PPR) in Next.js 15 for instant shell rendering.

GET STARTED

Ready to build
something exceptional?

From idea to launch in weeks, not months. Let's talk about your project.