On the homepage hero of my site I claim strong Core Web Vitals on every project — it’s the line that defines how I work as an Astro developer, and the constraint behind every performance build I take on. That phrase shows up in a lot of pitches these days, usually with no explanation of what it actually means. This post fixes that. No jargon, no buzzwords. Just what the three numbers are, what counts as good, and the practical things I do on a build to keep them green.
What are Core Web Vitals?
Core Web Vitals are three measurements Google uses to score the real-world experience of loading and using a web page. They’re not opinions about your design — they’re stopwatch readings from real Chrome users visiting your site. Google publishes them in Search Console, feeds them into search ranking, and uses them as the performance backbone of the Lighthouse report.
There are three of them, and each one answers a single, simple question:
- Largest Contentful Paint (LCP) — how long until the main thing on the page is on screen?
- Interaction to Next Paint (INP) — when I tap or click, how long until the page responds?
- Cumulative Layout Shift (CLS) — does the layout jump around while it loads?
That’s it. Three questions, three numbers. Everything else under the Core Web Vitals umbrella is a refinement of those three.
Largest Contentful Paint — the “is the page there yet?” metric
LCP measures the moment the biggest visible element finishes rendering — usually the hero image, the hero heading, or the first big block of text. It’s the closest a machine can get to the feeling of “OK, the page has loaded.”
Google’s thresholds are sharp:
- Good: under 2.5 seconds
- Needs improvement: 2.5 to 4 seconds
- Poor: over 4 seconds
A page that takes five seconds to show its hero will fail this on a mid-range phone, even on a fast connection. The usual culprits are a hero image that’s three times larger than it needs to be, a custom font that blocks rendering, or a JavaScript framework that won’t paint anything until it’s finished booting.
Interaction to Next Paint — the “did it hear me?” metric
INP is the newest of the three. It replaced an older metric called First Input Delay in March 2024, and it’s stricter — instead of only timing the very first interaction on the page, it tracks every tap, click, and key press across the visit and reports the slowest one.
The thresholds:
- Good: under 200 milliseconds
- Needs improvement: 200 to 500 milliseconds
- Poor: over 500 milliseconds
If a visitor taps a menu button and the menu opens 700 ms later, INP catches it. The usual cause is a long task on the main thread — a chunky third-party script, a hydration step that runs on every interaction, an analytics tracker that synchronously calls home before the click handler can finish. INP is the metric that punishes “JavaScript-everywhere” architectures the hardest.
Cumulative Layout Shift — the “stop moving!” metric
CLS measures how much the content on screen shifts position after it first appeared. It’s the reason you’ve tapped “Continue” on a checkout page and accidentally hit “Cancel” because an ad loaded above it half a second too late.
Unlike LCP and INP, CLS is a unitless score, not a time:
- Good: 0.1 or lower
- Needs improvement: 0.1 to 0.25
- Poor: above 0.25
The fix is almost always the same: reserve the space before the content arrives. Set width and height on every image. Give embeds and iframes a fixed aspect ratio. Don’t inject banners, cookie bars, or “subscribe!” modals into the document flow after the page has rendered — overlay them.
Where the numbers come from
Two sources, and they sometimes disagree on purpose.
- Lab data — a synthetic run, like the one Lighthouse and PageSpeed Insights perform. A simulated phone, throttled CPU, throttled network, cold cache. Useful because it’s reproducible and you can run it before shipping. Limited because it’s one device pretending to be the average visitor.
- Field data — the Chrome User Experience Report (CrUX). This is the real one. It’s an anonymised rolling 28-day window of measurements collected from actual Chrome users who visited your site on actual devices. This is what Google Search uses for ranking signals.
A page can score 100 in Lighthouse and still have a “Needs improvement” CrUX badge in Search Console, because real visitors are on a wider spread of devices and networks than the lab simulates. The goal is to win both — design and build against the lab number, then verify against the field number once you have traffic. There’s more on how the lab side fits in the broader Lighthouse score post.
How to improve Core Web Vitals on an Astro site
This is the part that turns the theory into a build. Roughly the order I work in when a project starts:
Pick a stack that ships less JavaScript. This is the single biggest lever. A site built on a framework that hydrates the entire page on load starts the INP race twenty metres behind. I default to Astro because it ships zero JavaScript by default and only hydrates the islands that genuinely need it. Same content, a fraction of the runtime cost.
Treat the hero image as a first-class budget item. The hero is almost always the LCP element. That means: served in a modern format (AVIF or WebP), sized to the viewport not to the desktop, preloaded in the document head so it starts downloading before the CSS even finishes parsing, and given an explicit width and height so it doesn’t shift the layout on arrival. One image, treated carefully, wins LCP and helps CLS at the same time.
Reserve space for everything that loads late. Every image gets dimensions. Every embed gets an aspect ratio. Every late-arriving block — cookie banner, share buttons, comment thread — overlays rather than pushes. CLS goes from “something I have to fix at the end” to “something I never had a problem with.”
Defer the third party. Analytics, chat widgets, ad scripts, video embeds — none of them block the first render. They load on idle, after interaction, or behind a click-to-play poster. INP stays under 200 ms because the main thread isn’t busy parsing somebody else’s bundle while the visitor is trying to tap something.
Self-host the font, and subset it. A custom font that’s served from a third-party CDN, in three weights, with every glyph in Unicode, costs you LCP every time. One self-hosted variable font, subsetted to Latin, preloaded, with font-display: swap — the page renders fast and the typography lands without a layout shift.
Measure twice — lab first, then field. Before I ship, every page runs through PageSpeed Insights on both mobile and desktop. After it ships and gets traffic, Search Console’s Core Web Vitals report is the source of truth. Lab catches regressions during development; field catches the ones that only show up on real devices.
Watch out for “performance debt.” Every new feature is weighed against the budget. A canvas animation that’s beautiful on desktop and costs three INP points on a mid-range Android is either rebuilt as a CSS animation, gated to wider viewports, or cut. That’s exactly the call I made for the LetterGlitch CTA on this site — it runs on desktop, it doesn’t on mobile, and the mobile INP stays green because of it.
How to verify a site yourself
Three free tools, in increasing order of detail:
- PageSpeed Insights — paste a URL, get lab and field readings side by side. Mobile and desktop in a single run. This is the fastest way to sanity-check any site, including mine.
- Google Search Console → Core Web Vitals — the real, 28-day field data for every page Google has measured on your site. Requires verifying ownership, but it’s the report that actually affects search.
- Chrome DevTools → Performance panel — open any page, press F12, click Performance, hit record, and interact with the page. DevTools now prints LCP, INP, and CLS live with the offending element highlighted, so you can see which image is causing a shift or which script is blocking a paint. This is where the old Web Vitals extension was merged in January 2025, so it’s now the official way to debug Core Web Vitals locally.
The bottom line
Core Web Vitals are three plain questions wearing acronyms. Is the page there? Does it respond? Does it stay still? Get those three right and the rest of the performance story — search ranking, conversion rate, bounce rate, the Lighthouse score — tends to follow.
The reason the homepage hero says “strong Core Web Vitals on every project” is that I treat them as a constraint from the first commit, not as something to patch on at the end. Pick a stack that ships less JavaScript, budget the hero image, reserve every late-loading block, defer the third party, and verify both in the lab and in the field. Do that and the green badge in Search Console isn’t a goal — it’s the default.
It’s the standard I hold on every site I build as a freelance Astro developer.