Cyber SEO: 50% off all annual plans
Preferences

Privacy is important to us, so you have the option of disabling certain types of storage that may not be necessary for the basic functioning of the website. Blocking categories may impact your experience on the website. More information (Cookie Policy)

Accept all cookies

Next.js SEO: Rendering, Metadata, Sitemaps and a Blog That Ranks

Next.js SEO guide: pick SSG, SSR or ISR, set metadata and canonicals, generate sitemap.xml, run a webhook-fed blog and stay readable by AI crawlers.

Published on:
25/10/2026
-
Updated on:
25/10/2026
Cover of the Sorank guide to Next.js SEO, showing a server-rendered page with its metadata, sitemap and blog routes

Tools

Thibault Besson-Magdelain, founder of Sorank

About Author

Thibault Besson-Magdelain

Founder of Sorank, 7+ years of experience in SEO, GEO enthusiast.
On this page

In short

Next.js is one of the best React frameworks for SEO because it sends complete HTML to crawlers instead of an empty shell. To rank, prerender content pages (static generation or ISR), define titles, descriptions and canonicals with the Metadata API, generate sitemap.xml and robots.txt from the app folder, use real links and correct status codes, and keep your main content out of client-only code, since most AI crawlers do not run JavaScript.

Want to go further? Ask

Quick quiz

Is SEO right for you, and how should you start?

4 quick questions to see if Google can bring you customers.

Question 1 of 425%
Do people search Google for what you sell?

Next.js SEO is mostly about making the right choice per route: what is rendered on the server, what is cached, and what reaches the HTML before any script runs. Google explains in its JavaScript SEO basics that it processes JavaScript apps in three phases (crawling, rendering, indexing) and that "server-side or pre-rendering is still a great idea". Next.js does that by default. This guide covers the App Router (Next.js 13 and later), with notes for the older Pages Router.

Is Next.js good for SEO?

Yes. A plain React app built with client-side rendering sends a nearly empty HTML file and builds the page in the browser; search engines must render it, and many bots never do. Next.js renders React on the server, so the HTML response already contains the headings, text, links and metadata. Our guide to JavaScript SEO explains why that difference matters for indexing.

In the App Router, components are Server Components by default. Even components marked 'use client' are prerendered to HTML on the server. The weak spot is data: anything you fetch inside useEffect, or load only after a click, is missing from the initial HTML. Fetch content in Server Components, and keep client components for interactivity.

SSG, SSR, ISR or CSR: which rendering mode should you choose?

Next.js lets you mix modes route by route. The choice affects freshness, speed and what crawlers receive.

ModeWhen the HTML is builtSEO verdictGood for
Static generation (SSG)At build timeBest: full HTML, very fastLanding pages, docs, evergreen articles
Incremental Static Regeneration (ISR)At build, then refreshed in the background or on demandBest for large or changing sitesBlogs, product catalogs, CMS pages
Server-side rendering (SSR)On every requestGood: full HTML, depends on server speedPersonalized or real-time pages
Client-side rendering (CSR)In the browserWeak: content invisible to most botsDashboards behind a login

The Next.js ISR documentation lists the benefits: update static content "without rebuilding the entire site" and handle large amounts of pages without long build times. A route with export const revalidate = 3600 is regenerated at most once an hour; for exact control, call revalidatePath or revalidateTag when content changes. Note that ISR does not work with a static export (output: 'export'). For apps that must stay client-rendered, our guide to single page application SEO covers the workarounds.

Tip

Check what bots receive, not what your browser shows: run curl on the URL or open view-source and search for a sentence from the article. If it is not in the raw HTML, it depends on JavaScript.

How do you set titles, descriptions and canonicals with the Metadata API?

The Metadata API replaces next/head in the App Router. According to the Next.js metadata documentation, you export a static metadata object from a layout or page, or a generateMetadata function when the values depend on data, and Next.js generates the head tags. Both are only supported in Server Components.

export async function generateMetadata({ params }) {
  const { slug } = await params
  const post = await getPost(slug)
  return {
    title: post.title,
    description: post.excerpt,
    alternates: { canonical: `/blog/${slug}` },
    openGraph: { images: [post.cover] },
  }
}

Five rules that prevent most problems:

  • Set metadataBase in the root layout (your production domain), so relative canonicals and Open Graph URLs become absolute.
  • Use a title template in the root layout, such as '%s | Brand', so every page gets a unique title with the brand once.
  • Give every indexable page a self-referencing canonical through alternates.canonical; it protects against duplicates created by query parameters and trailing slashes. Our glossary entry on the canonical tag covers the rules.
  • Write a description per page, generated from the content in generateMetadata, never one site-wide default.
  • Add Open Graph images with an opengraph-image file in the route folder, and check the result with an Open Graph preview tool.

On dynamic pages, Next.js streams metadata after the first bytes to speed up rendering. The documentation states that streaming is disabled for bots that expect metadata in the head, detected by user agent (Bingbot, Twitterbot and Slackbot are among the examples), and that the htmlLimitedBots option customizes the list. If you care about a crawler that is not covered, add it. On the Pages Router, the equivalent is the Head component from next/head, with a key attribute to avoid duplicate tags.

How do you generate sitemap.xml and robots.txt in Next.js?

Both are special files in the app folder. A sitemap.ts file that exports a function returning URLs becomes /sitemap.xml; a robots.ts file becomes /robots.txt. The sitemap reference notes that the file is cached by default and that Google's limit is 50,000 URLs per sitemap; above that, generateSitemaps splits it into several files.

import type { MetadataRoute } from 'next'

export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
  const posts = await getPosts()
  return posts.map((p) => ({
    url: `https://example.com/blog/${p.slug}`,
    lastModified: p.updatedAt,
  }))
}

Include only canonical, indexable URLs that return 200, and use the real update date in lastModified. The sitemap also accepts alternates.languages for multilingual sites. In robots.ts, point to the sitemap and decide which AI bots may crawl the site; our article on robots.txt for AI crawlers lists them. More on the format in our glossary entry on the XML sitemap.

Which technical details break Next.js SEO most often?

ProblemWhat happensFix
Navigation with onClick and router.pushGoogle only follows a elements with an hrefUse the Link component from next/link, which renders a real link
Missing content rendered as a 200 pageSoft 404 in Search ConsoleCall notFound() so the route returns a 404 status
Temporary redirects for moved pagesredirect() sends a 307Use permanentRedirect() or permanent: true in next.config (308)
Mixed trailing slashesTwo URLs for the same pagePick one with the trailingSlash option and keep canonicals consistent
Preview or staging deployments indexedDuplicate copies of the site in GoogleSend noindex on non-production domains
Content behind tabs loaded on clickText absent from the HTMLRender all content on the server and hide it with CSS if needed

These issues all reduce crawlability: a crawler must be able to discover each URL through links and get a clean status code.

How do you add structured data in Next.js?

The Next.js documentation recommends rendering JSON-LD as a script tag of type application/ld+json directly in the page or layout component, built from the same data as the page, and escaping the < character in the serialized JSON to prevent injection. Because it is rendered on the server, Google and AI crawlers both see it in the raw HTML. Use Article (or BlogPosting) for posts, Organization in the root layout, BreadcrumbList for deep pages and Product for e-commerce. A schema generator gives you a valid starting block, then validate the page with Google's Rich Results Test.

How do you make a Next.js site fast enough for Core Web Vitals?

Next.js ships the components that handle the usual causes of poor Core Web Vitals:

  • next/image: resizes images, serves modern formats, lazy-loads by default and requires dimensions, which prevents layout shifts. Mark the main image above the fold as a priority so it is not lazy-loaded (it is usually the Largest Contentful Paint element).
  • next/font: self-hosts fonts and avoids the shift caused by late font swaps.
  • next/script: loads third-party scripts with a strategy (afterInteractive, lazyOnload) instead of blocking the page.
  • Less client JavaScript: every 'use client' boundary adds code to download and hydrate, which weighs on Interaction to Next Paint on mobile.

Measure field data, not only a lab score: our guide to PageSpeed Insights shows how to read both.

How do you run a blog on Next.js that ranks?

A Next.js blog usually takes one of three forms: MDX or Markdown files in the repository (simple, but every post needs a commit and a deploy), a headless CMS (Sanity, Contentful, Strapi, Payload) fetched in Server Components, or a publishing webhook that receives articles from an external tool. In all three cases the SEO pattern is the same: a dynamic route app/blog/[slug] with generateStaticParams, generateMetadata, ISR, the sitemap fed from the same source, and an index page that links every post.

The webhook pattern keeps publishing out of your deploy cycle. A Route Handler receives the article, stores it, then revalidates the affected pages:

// app/api/publish/route.ts
import { revalidatePath } from 'next/cache'

export async function POST(request) {
  if (request.headers.get('authorization') !== `Bearer ${process.env.PUBLISH_SECRET}`) {
    return new Response('Unauthorized', { status: 401 })
  }
  const article = await request.json()
  await savePost(article)
  revalidatePath('/blog')
  revalidatePath(`/blog/${article.slug}`)
  return Response.json({ ok: true })
}

Watch out

Protect the endpoint with a secret, and revalidate the exact public path. The ISR documentation warns that with several server instances and the default file cache, on-demand revalidation only clears the instance that receives the call; use a shared cache handler.

How does Next.js SEO help you get cited by AI assistants?

Server rendering is the first condition for GEO (generative engine optimization). Vercel's December 2024 analysis The rise of the AI crawler found that "none of the major AI crawlers currently render JavaScript", naming GPTBot, ChatGPT-User, OAI-SearchBot, ClaudeBot and PerplexityBot, and counted 569 million GPTBot fetches and 370 million Claude fetches on its network in one month. A Next.js page that prerenders its text, headings and JSON-LD is readable by all of them; a client-rendered page is not.

The second condition is content worth citing: articles that answer one question per section, with sources, figures and clear definitions, published regularly. That is the part Sorank, our product, automates. Sorank is an autopilot SEO and GEO software: it finds your keywords, and its blog article generator writes 20, 60 or 120 articles per month with sources, internal links and images. On a Next.js site, it connects through the custom webhook described on the installation page: your Route Handler receives each article, saves it and revalidates the blog. AI mention tracking then checks every week whether ChatGPT, Claude and Gemini cite your brand.

Sorank blog article generator form creating an SEO article from a target keyword

The short version: prerender every page you want found, define metadata on the server, and feed the sitemap from the same source as the content. Next.js gives you the tools; rankings and AI citations come from what you publish with them. To keep a Next.js blog supplied with articles, see Sorank's plans, from $49 per month with a 3-day free trial.

Frequently asked questions

Is Next.js better than React for SEO?

Next.js is built on React, so the comparison is between rendering approaches. A default React single page app renders in the browser and sends almost empty HTML, while Next.js prerenders pages on the server or at build time. Crawlers, including AI bots that do not run JavaScript, receive complete content from Next.js without extra setup.

Does Next.js generate a sitemap automatically?

Not by itself. In the App Router you add a sitemap.ts file to the app folder that returns your URLs, and Next.js serves it at /sitemap.xml. For large sites, generateSitemaps splits the list into several files, since Google accepts up to 50,000 URLs per sitemap.

Should I use the App Router or the Pages Router for SEO?

Both can rank well because both prerender HTML. The App Router is the recommended choice for new projects: Server Components reduce client JavaScript, and the Metadata API, sitemap.ts and robots.ts handle SEO files natively. On an existing Pages Router site, migrating is rarely worth it for SEO alone.

Our Blog for Ambitious Company

Our free SEO tools

See all our free tools

THEY TRIED SORANK BEFORE YOU

Testimonials from ambitious founders

Organic growthE-commerce

0 to 10000 visitors in 5 months

Celio Fabianomonrobotlavevitre.fr
Organic growthSoftware

0 to 5000 clients in 8 months

Thibault BMsorank.com
Organic growthLeisure and aviation

0 to 1104 clicks in 4 months

Dominiqueflight-sensations-idf.com
Organic growthMusic software

x30 clicks in 4 months

Valentin Cordiertiger-sounds.com
Organic growthHealth and wellness

x30 clicks in 4 months

Rodrigue Bretonalthevia.com