The Core Web Vitals checklist we ship every project against
LCP, CLS and INP are not mysterious. A short, repeatable checklist that keeps every site we ship in the green from the first deploy.

Core Web Vitals reward boring, disciplined engineering. There is no single trick and no plugin that fixes them after the fact. There is a short list of things you do on every project, and if you do all of them, the scores take care of themselves. This is the checklist we ship against, and it is a big part of our performance and SEO work.
First, a word on why this matters beyond a green dashboard: Core Web Vitals are a ranking signal, and they correlate with the things users actually feel. A fast site converts better and ranks better. The metrics are just a measurable proxy for "this page respects the person using it."
Largest Contentful Paint (target under 2.5s)
LCP measures when the biggest thing in the viewport finishes rendering, usually the hero image or the hero headline. Two rules cover most cases:
- Mark the hero image as priority so it is not lazy-loaded, and give the browser the right
sizesso it picks the correct source. - Self-host fonts with
font-display: swapso text paints immediately instead of waiting on a font download.
import Image from "next/image";
<Image src={hero} alt="" priority sizes="100vw" />;Beyond the hero, LCP is mostly about not blocking the critical path. Avoid render-blocking scripts, keep the initial HTML small, and serve it from a CDN. If your largest element is an image, optimizing your images is usually the highest-leverage fix you can make.
Cumulative Layout Shift (target under 0.1)
CLS measures how much the page jumps around as it loads. It is the most annoying failure to experience and the easiest to prevent if you plan for it. Layout shift comes from elements that change size after they paint, so reserve the space up front:
- Every image and embed gets explicit width and height (or an aspect ratio).
- Animations move only
transformandopacity, neverheight,topormargin. - Fonts use
swapwith a metrics-matched fallback so the swap does not reflow the page. - Anything injected late (banners, ads, cookie bars) gets reserved space, not a sudden push.
CLS is a discipline, not an optimization. If you reserve space as you build, you will basically never see a layout-shift problem.
Interaction to Next Paint (target under 200ms)
INP measures how quickly the page responds to input across the whole session, not just the first click. The lever is simple to say and harder to honor: ship less JavaScript, and keep the main thread free.
- Keep interactive components as small client islands rather than hydrating whole pages.
- Lazy-load anything below the fold so it is not competing for the main thread on first paint.
- Do expensive work at build time or on the server, not in a
useEffectafter the user is already trying to interact.
This is where rendering strategy and performance meet. The smaller your client bundle, the less work the browser does between a tap and a response. Our mental model for App Router rendering is really a performance article wearing an architecture hat.
Measure, do not guess
Lab tools like Lighthouse are great for catching regressions in development, but they run on one synthetic device. Real users are the truth. Watch field data (the Chrome User Experience Report, or real-user monitoring) so you are optimizing what people actually experience, not a number on your fast laptop. A page can score 100 in the lab and still feel slow for someone on a three-year-old phone.
Make it a habit, not a heroic effort
The reason this checklist works is that none of it is last-minute. Priority images, reserved space, small client islands, swap fonts, and build-time work are decisions you make while building, not optimizations you bolt on the week before launch. The static-first approach we describe in shipping a site without a database gives you most of this for free.
Bake the habits in, measure with real-user data, and every deploy lands in the green without anyone having to be a hero about it.

