Many developers assume that moving to a static architecture automatically means a perfect performance score. In my experience, that’s a dangerous assumption. While the server-side latency is gone, client-side bottlenecks—like oversized JS bundles and unoptimized images—can still tank your rankings. Optimizing Core Web Vitals for JAMstack isn’t about a single ‘magic button’; it’s about a series of targeted refinements to how your browser renders content.

Whether you’re debating Astro vs Next.js for static sites or you’ve already deployed your project, the goal remains the same: a seamless, instant user experience. In this tutorial, I’ll walk you through the exact workflow I use to hit those elusive 100s in PageSpeed Insights.

Prerequisites

Step 1: Eliminating LCP (Largest Contentful Paint) Bottlenecks

LCP measures how long it takes for the largest visible element to render. In most JAMstack sites, this is the hero image or a large H1 heading. If your hero image is being lazy-loaded, you’re actively hurting your LCP.

Prioritize the Hero Image

I’ve found that adding a fetchpriority="high" attribute to the LCP image is the fastest way to see a gain. Here is how I implement it in a modern React/Next.js environment:

<!-- Avoid lazy loading for the LCP element -->
<img 
  src="/hero-banner.webp" 
  alt="Product Showcase" 
  fetchpriority="high" 
  loading="eager" 
  width="1200" 
  height="600" 
/>

Optimize Image Formats

Stop using JPEGs for everything. Move to WebP or AVIF. If you are using a framework like Astro, I highly recommend their built-in image component which handles this automatically at build time.

Step 2: Reducing CLS (Cumulative Layout Shift)

CLS is that annoying jump that happens when an image loads and pushes the text down. It’s a primary reason for poor user experience scores.

Set Explicit Dimensions

Never let the browser guess the size of your images. Always provide width and height attributes. This allows the browser to reserve the space before the asset actually downloads.

Manage Dynamic Content and Fonts

Web fonts are a common source of CLS. When a custom font loads, it often replaces a system font with a different width, causing a “flash of unstyled text” (FOUT). To fix this, use font-display: swap; in your CSS, or better yet, use a tool like Next/font to self-host your fonts.

As shown in the technical diagram below, the flow of resource loading significantly impacts how the browser calculates layout stability. If you want to know if JAMstack is still worth it in 2026, the answer is yes—specifically because of how much control we have over these rendering paths.

Technical diagram showing the browser rendering pipeline for JAMstack sites, highlighting the difference between a blocking layout shift and a reserved space layout
Technical diagram showing the browser rendering pipeline for JAMstack sites, highlighting the difference between a blocking layout shift and a reserved space layout

Step 3: Improving Interaction to Next Paint (INP)

INP has replaced FID as a primary metric. It measures the overall responsiveness of the page. In JAMstack, the biggest killer of INP is “Hydration Overload”—where the browser is so busy turning static HTML into a reactive app that it ignores user clicks.

Implement Partial Hydration (Islands Architecture)

If you have a massive page but only the search bar is interactive, why hydrate the whole page? This is where the “Islands Architecture” shines. By only hydrating the components that need it, you free up the main thread.

<!-- Example: Astro component approach -->
<!-- This component renders as static HTML (Zero JS) -->
<StaticHeader />

<!-- This component is hydrated only when it enters the viewport -->
<InteractiveCart client:visible />

Pro Tips for Advanced Optimization

Troubleshooting Common Issues

“My Lighthouse score is great on desktop but poor on mobile”

This is usually due to CPU throttling. Mobile devices process JavaScript much slower than your M3 MacBook. Test your site using “Applied Throttling” in Chrome DevTools to see the real-world experience of a user on a mid-range Android device.

“Images are still shifting despite having dimensions”

Check if you have CSS like width: 100%; height: auto; without a wrapping container that has a defined aspect ratio. Use the CSS aspect-ratio property to maintain the box size.

What’s Next?

Once you’ve mastered optimizing Core Web Vitals for JAMstack, the next step is implementing a continuous monitoring system. I recommend setting up CrUX (Chrome User Experience Report) monitoring to see how real users—not just synthetic bots—are experiencing your site.

Ready to scale your performance? Check out my other guides on JAMstack architecture best practices to ensure your site remains fast as it grows.