JavaScript Framework SEO

SEO for JavaScript frameworks — React, Next.js, Vue, Nuxt, Angular, Svelte, and Astro. How rendering mode (SSR, SSG, CSR) determines what Google can index, and which frameworks handle SEO best out of the box.

First published: Jun 26, 2026 · Last updated: Jul 19, 2026 · Advanced
demand #5 in Platform SEO#53 in Technical SEO#73 on the site

JavaScript framework SEO comes down to rendering mode: SSG and SSR give Googlebot pre-built HTML; CSR requires JavaScript execution that may or may not succeed. Next.js and Nuxt have the most built-in SEO support (SSR, SSG, ISR, metadata APIs). Pure React and Vue in CSR mode are the riskiest for SEO. Astro's island architecture is excellent for SEO by default. Angular requires SSR via @angular/ssr (formerly Angular Universal) for reliable indexation.

TL;DR — At the technical level, JS framework SEO is about: (1) rendering architecture for the initial HTML payload, (2) metadata injection into <head> before the response is sent, (3) how the framework handles hydration and link discovery, and (4) ISR cache staleness. Next.js has the most complete built-in SEO tooling (Metadata API, built-in app/sitemap.ts, image optimization). Astro is the most SEO-safe by architecture.

Rendering mode, metadata API, and ISR support by framework

Framework capabilities and defaults change by version; verify them in each framework’s official documentation. Evidence for this claim Primary standard or official documentation supporting the adjacent article claim. Scope: Protocol semantics and Search behavior are kept separate; no indexing, ranking, or migration-timing guarantee is inferred. Confidence: high · Verified: web.dev: Rendering on the Web No rendering mode guarantees indexing or rankings. Evidence for this claim Primary standard or official documentation supporting the adjacent article claim. Scope: Protocol semantics and Search behavior are kept separate; no indexing, ranking, or migration-timing guarantee is inferred. Confidence: high · Verified: Google: JavaScript SEO basics When you’re comparing frameworks for a decision, test the same routes, content, deployment target and tooling for each candidate — a benchmark that swaps any of those isn’t measuring the framework, it’s measuring the difference in setup.

FrameworkDefault renderingBuilt-in metadata APISSR/SSG supportEcosystem SEO support
AstroSSG (islands)Yes (<head> in .astro files, Content Collections for structured data)BothStrong
Next.jsSSR/SSG (configurable)Yes (Metadata API in App Router)Both + ISRExcellent
NuxtSSR by defaultYes (useHead, useSeoMeta)Both + ISRExcellent
SvelteKitSSR by defaultYes (svelte:head)BothGood
React Router (framework mode)SSR by defaultYes (meta export)SSR + DeferredGood
AngularCSR by defaultVia Angular Meta/Title servicesVia @angular/ssrModerate
React (bare)CSRManual (react-helmet-async; react-helmet is unmaintained)Via Next.js/GatsbyDepends on wrapper
Vue (bare)CSRManual (@unhead/vue; vue-meta is unmaintained)Via NuxtDepends on wrapper

Remix v2 and React Router v7 merged — Remix’s server rendering and data-loading model now ships as React Router’s “framework mode,” and that’s the stable upgrade path for Remix v2 apps. Remix 3 is a separate, experimental React-less rewrite (beta), not the successor to Remix v2 — don’t treat it as a drop-in SSR option for a React codebase.

Metadata injection timing — Metadata (<title>, <meta>) must be in the server response, not added by JavaScript after page load. Next.js’s Metadata API, Nuxt’s useSeoMeta, and Astro’s <head> component handle this correctly. document.title = '...' or React Helmet in CSR mode does not — it runs after the initial HTML is served.

Link discovery — Googlebot discovers links by parsing HTML. Links added via JavaScript (onClick, dynamic routing without <a> tags) may not be discovered. Use real <a href> elements for important navigation.

Hydration and duplicate content — If SSR and CSR render different content (hydration mismatch), you may end up with indexed content that doesn’t match what users see. Test for hydration errors in the browser console.

Soft 404s — Client-side routers can silently render a “page not found” UI while returning a 200 HTTP status. Search engines index these as real pages. Make sure your 404 page returns a real 404 status, and server-side redirects return 301.

ISR cache invalidation — In Next.js and Nuxt ISR setups, stale pages can be served to crawlers during the revalidation window. Set a time-based revalidate interval, and for content that changes on a schedule you don’t control (a CMS save, for example), pair it with on-demand revalidation triggered from a webhook-backed route handler — see the Next.js ISR guide for the full API.

// app/blog/[id]/page.tsx — time-based revalidation
export const revalidate = 3600 // re-check this page at most once an hour

// app/api/revalidate/route.ts — on-demand revalidation, called by a CMS webhook
import { revalidatePath } from 'next/cache'
import { NextRequest, NextResponse } from 'next/server'

export async function POST(request: NextRequest) {
  const { path, secret } = await request.json()
  if (secret !== process.env.REVALIDATE_SECRET) {
    return NextResponse.json({ message: 'Invalid secret' }, { status: 401 })
  }
  revalidatePath(path) // e.g. '/blog/1' — next request regenerates fresh HTML
  return NextResponse.json({ revalidated: true })
}

Add an expert note

Pin an expert quote

New person? Create their unclaimed profile at /admin/experts/ → Pin an expert quote first.