Skip to content
← Back to blog
Comparison

Astro vs Next.js SEO: Core Web Vitals and the Catch

Astro vs Next.js SEO compared on Core Web Vitals: Astro's zero-JS islands win by default, Next.js Server Components close most of the gap. How to pick.

By Mitrasish, Co-founderJul 2, 202612 min read
Astro vs Next.js SEO: Core Web Vitals and the Catch

Astro vs Next.js SEO comes down to one variable neither framework can dodge: how much JavaScript reaches the browser before your Core Web Vitals scores lock in. Get that variable right and canonicals, sitemaps, and structured data are a solved problem in both frameworks. Get it wrong and no amount of metadata tuning saves a slow page.

Astro vs Next.js SEO: the short answer

Astro wins Core Web Vitals by default for a content-only blog: its islands architecture ships no JavaScript unless a component asks for it, so Largest Contentful Paint (LCP) and Interaction to Next Paint (INP) start clean without any tuning. Next.js's App Router closes most of that gap with Server Components and streaming, and pulls ahead the moment the site needs auth, a dashboard, or per-user content sitting next to the blog.

Neither answer is universal, and that is the actual decision repo-based blog owners face. A marketing site with a blog bolted on has different constraints than a SaaS product with a blog living inside the same app as the dashboard. The rest of this post works through why JavaScript weight drives the scores, where each framework earns its keep, and how to keep the SEO fundamentals airtight regardless of which one you pick.

Why JavaScript weight moves Core Web Vitals in the first place

Every kilobyte of JavaScript the browser downloads, parses, and executes competes with the work of painting your content and responding to a click. A framework's default JavaScript footprint is not a cosmetic detail; it is the single biggest lever most sites have over their Core Web Vitals scores, ahead of image optimization, font loading, or CDN choice.

That lever matters because most sites are still failing the test. The 2025 Web Almanac measured that only 48% of websites achieve "good" Core Web Vitals on mobile and 56% on desktop, against the standard thresholds of LCP at or under 2.5 seconds, INP at or under 200 milliseconds, and Cumulative Layout Shift (CLS) at or under 0.1. Just over half the web clears the bar on desktop; fewer than half do on mobile, where JavaScript's cost in parse and execution time is highest.

LCP, CLS, and INP: what each one actually measures

LCP measures how long it takes the largest visible element, usually a hero image or the main heading, to render. CLS measures how much visible content shifts unexpectedly after it first appears, the classic case being an ad or image that loads late and pushes the text you were reading down the page. INP measures how quickly the page responds to a user's interaction, replacing the older First Input Delay metric with a measure that covers the full interaction, not just the first one.

All three are sensitive to JavaScript in different ways. A large JS bundle delays LCP because the main thread is busy parsing and executing instead of painting. It hurts CLS when late-loading scripts inject content into a page that already rendered without reserving space for it. It hurts INP directly: a busy main thread cannot respond to a click until it finishes whatever JavaScript task it is already running.

Astro's zero-JS-by-default model (islands architecture)

Astro's core mechanism is the islands architecture: every UI component renders to static HTML and CSS by default, with all client-side JavaScript stripped out automatically. Interactivity is opt-in per component through a client:* directive, so a comment widget or a search box ships its own JavaScript while the surrounding article, headings, and images ship none.

Astro's own documentation is direct about the reasoning: "This avoids the monolithic JavaScript payloads that slow down the responsiveness of many other, modern JavaScript web frameworks." For a blog post with no interactive elements at all, that means the page can ship effectively zero JavaScript and still render the full page, images included, which is why Astro's default Core Web Vitals scores for content sites are hard to beat without deliberate effort in another framework.

Where Next.js's JS weight comes from, and how streaming/RSC cuts it

The reputation Next.js has for heavier pages comes from its Pages Router era and from React apps in general, where every component, including static ones, shipped as client-side JavaScript to be hydrated in the browser. The App Router changes the default: pages are Server Components unless marked otherwise, and Server Components render on the server with their code and dependencies never sent to the client at all. A blog post with no interactive widgets can be built entirely of Server Components and ship no more JavaScript than an equivalent Astro page.

Streaming is the other half of the story. The App Router streams HTML in chunks aligned to <Suspense> boundaries instead of waiting for every data fetch to resolve before sending anything. Next.js's own guidance is blunt about the alternative: "Without streaming, the server waits for all data before sending any HTML, so TTFB equals the slowest query. With streaming, the server sends the static shell as soon as it's ready." That static shell, your layout, navigation, and fallback content, paints immediately, and Next.js's own advice is to keep the LCP element (a hero image or the main heading) outside any Suspense boundary so it renders in that shell rather than waiting on a slow fetch.

Streaming also improves INP through selective hydration: each Suspense boundary hydrates independently, so React can prioritize hydrating whatever section the user is actually touching instead of blocking on the whole page in one pass. None of this is theoretical. Frigade's own case study moved a client-rendered Pages Router site to Server Components on the App Router. Bundle size dropped 62%. Speed Index, measured with Pingdom Speedtest and PageSpeed Insights, came in 63% faster. That gap did not come from a framework limitation; it came from an architecture the App Router was built to fix.

When Astro's zero-JS approach wins

Content-first blogs, docs, and marketing sites

If the site is mostly text, images, and links, with a handful of interactive widgets at most, Astro's default gets you a fast, low-JavaScript page without having to think about it. This is Vercel's own framing too, and Vercel maintains Next.js, so it has no reason to undersell Astro: Vercel's comparison recommends Astro for "purely static content sites," naming blogs, documentation portals, marketing sites, and portfolios specifically, and describes its strength as shipping "minimal client-side JavaScript" with "isolated interactivity" for the few components that need it, like a search bar or a signup form.

That is the profile of most repo-based blogs: a founder or a small team publishing posts as Markdown files, with a comment widget or a newsletter signup at most for interactivity. For that shape of site, reaching for Astro is not a performance hack, it is matching the tool to the job.

When Next.js's weight is worth it

Auth, dashboards, and personalization at scale

The moment the site is not just a blog, when the same repo also serves a logged-in dashboard, a checkout flow, or content that varies per user, Next.js's App Router earns its extra weight. Server Actions let a form submission run a mutation on the server. The caching and revalidation system then returns updated data and re-rendered UI in a single round trip, commonly gated behind an auth() check inside the action itself.

Astro does not compete on this ground by design. Astro has no official first-party authentication solution; auth runs through community integrations or third-party providers like Supabase, Firebase, or Better Auth, wired up through Astro's middleware and context.locals. That works, but it is assembled, not built in. Vercel's own comparison puts it plainly: Next.js is "the better choice" for "SaaS dashboards, collaborative tools, marketplaces, and commerce apps where every route involves server-side logic and user-specific data," and frames it as "the safer starting point" for a site that might grow from static content into app-like interactivity, since that growth does not require a framework migration.

Astro's server islands: personalization without going full-app

Astro's answer to that gap is narrower but real. Server Islands, enabled with a server:defer directive, let a mostly-static page render instantly with fallback content while one specific dynamic or personalized component, a logged-in user's avatar, say, fetches and streams in separately, without making the rest of the page dynamic.

That closes a meaningful slice of the personalization gap without adopting Next.js's full application model: a content site can show "Welcome back, Alex" in the corner while the article itself stays static and fast. It does not give Astro Server Actions, a first-party auth story, or the caching and revalidation system Next.js builds mutations around. For a blog with one personalized widget, Server Islands are usually enough. For an app where most routes need session state, Next.js is still the more direct route.

Build speed: does it actually matter for a blog-sized repo

Build time comes up in every framework debate, and for a blog-sized repo, it should not decide anything. Both frameworks statically generate content at build time, Astro by default, Next.js through generateStaticParams in the App Router, and a repo with a few hundred Markdown posts builds in well under a couple of minutes on either one. The variable that actually separates them is runtime JavaScript weight, not the minutes your CI spends building the site. If build time is the deciding factor in your framework choice, that is usually a sign the real question, how much JavaScript ships to readers, has not been asked yet.

Keeping SEO airtight in either framework

Whichever framework you pick, the technical SEO fundamentals do not change: a self-referencing canonical, a sitemap that reflects your actual URLs, and structured data that validates. Both frameworks handle all three; the mechanics just differ.

Metadata, canonicals, and sitemaps (generateMetadata vs @astrojs/sitemap)

In the Next.js App Router, each page's metadata, including its canonical URL, comes from generateMetadata, and sitemap.ts generates the sitemap, with a generateSitemaps function available to split output once you approach Google's cap of 50,000 URLs per sitemap file. These are Route Handlers, so they are cached by default. If you want that correctness enforced automatically rather than eyeballed per PR, our GitHub Actions SEO checks post covers a CI job that parses the built HTML for a missing canonical or a mismatch before merge.

Astro's equivalent is the @astrojs/sitemap integration, which generates sitemap-index.xml and sitemap-0.xml at build time once you set the site option in astro.config. The one gap worth knowing up front: it cannot generate sitemap entries for dynamic routes when the site runs in SSR mode, which matters if you lean on Server Islands for personalized routes alongside a mostly-static blog.

Structured data and robots files

Neither framework does anything magic here; both just give you a place to put the JSON-LD and the robots directives correctly. Next.js's robots.ts and sitemap.ts file conventions and Astro's config-driven equivalents both compile to the same static output Google reads. The mistake that actually costs rankings is not a framework limitation, it is a malformed JSON-LD block or a canonical pointing at the wrong URL shipping quietly because nobody checked the built HTML before merge.

A decision checklist for a repo-based blog choosing between them

If your repo is...Lean toward
A blog, docs site, or marketing site with no logged-in areaAstro
A blog that will always stay separate from any app/dashboardAstro
A blog living inside a product repo that already has auth, a dashboard, or Server ActionsNext.js
Planning to add personalization, checkout, or user accounts laterNext.js
Only need one or two personalized widgets on otherwise static pagesEither: Astro Server Islands or Next.js Suspense both cover this
Migrating an existing Next.js app and adding a blog to itNext.js, don't split frameworks for one section

We ran this exact checklist on our own site. Trylyra.ai is a marketing page plus a blog with no auth and no dashboard, the textbook case for Astro. We built it on Next.js's App Router anyway, because the same repo also needs to grow into the product dashboard later, and splitting frameworks for one section was not worth maintaining two build pipelines for a team our size. That is the trade-off this checklist is for: it is not always the framework with the better default score, it is the one that matches what the rest of your repo already is.

If none of the app-like requirements apply, default to Astro and take the Core Web Vitals win with less engineering effort. If the blog shares a repo with a product that already needs auth or a dashboard, Next.js's App Router gets you comparable scores with one codebase instead of two. Either way, the framework choice is a one-time decision your SEO strategy does not depend on nearly as much as the discipline you bring to canonicals, sitemaps, and shipping verified content on top of it.

For teams whose blog already lives in one of these repos and just needs posts written and reviewed without babysitting the frontmatter, that is the exact slot our AI blog writer for developers is built for: it reads your repo, drafts in your voice, and opens a pull request against whichever framework you picked. If you want to see how that looks against your own stack, request early access and tell us which of the two you are on. The workflow is the same either way, a Git-based AI blog writer commits a .md file to a branch and opens a PR, since neither Astro nor Next.js changes what a reviewable diff looks like.

Whether your blog runs on Astro or Next.js, Lyra reads your repo's conventions and opens a pull request that fits either one. Talk to the founder → · Join the waitlist

FAQ

Frequently asked

Does Astro beat Next.js on Core Web Vitals?+

For a content-only blog, usually yes, and by default. Astro renders every component to static HTML and strips client-side JavaScript unless a component explicitly opts into a client:* directive, so a typical post ships close to zero JavaScript. Next.js can match that with the App Router's Server Components and streaming, but it takes deliberate architecture, not a default setting.

Can Next.js match Astro's performance for a content site?+

Largely, yes. Next.js App Router pages are Server Components by default, so server-only code and its dependencies never reach the client bundle, and streaming lets the static shell (including your LCP element) render before any slow data resolves. Frigade measured a 62% JS bundle reduction and a 63% faster Speed Index after moving a client-rendered Pages Router app to Server Components, which shows how much of the old Next.js weight was avoidable rather than inherent.

Which framework is better for SEO, Astro or Next.js?+

Both handle core technical SEO, canonicals, sitemaps, structured data, robots files, fine, so the choice is not really about SEO. It is about Core Web Vitals effort and what the site needs beyond the blog. Astro gets you there with less engineering discipline; Next.js gets you there with more control if you also need auth, a dashboard, or personalization.

Do Astro's Server Islands remove the need for Next.js?+

They remove the need for some of it. Astro's server:defer directive lets a mostly-static page render instantly with fallback content while one dynamic, personalized component streams in separately, so a logged-in user's avatar or a live cart count no longer forces the whole page into a dynamic render. It narrows the gap; it does not give Astro Next.js's full Server Actions and auth ecosystem.

Does switching frameworks affect existing SEO rankings?+

Not directly, Google ranks content and technical correctness, not the framework name, but a migration can absolutely break rankings if canonicals, redirects, or sitemaps regress in the process. Treat a framework migration like any other technical SEO project: verify every canonical and redirect before and after, and gate the change behind CI checks rather than a manual spot check.

Built by the tool you're reading about

This post is the kind of thing Lyra ships on her own.

Lyra finds the topics worth ranking for, writes them in your repo's voice, fact-checks every claim, and opens a pull request scored and ready to merge. You review and hit merge. Want to see what she'd write for you? Tell us about your blog and the founder will walk through it with you.

Astro vs Next.js SEOCore Web Vitals Framework ComparisonNext.js Server Components SEOAstro Islands Architecture SEOAstro vs Next.js Blog