Topic

SEO for Next.js

Next.js App Router SEO — metadata API, dynamic OG images, sitemaps, canonicals, structured data, and Core Web Vitals. Everything a dev needs to ship a well-optimized site.

Next.js has become the default framework for production web apps, and the App Router — stable since Next.js 13.4 — makes it one of the best platforms for technical SEO. The primitives are in the right places: metadata lives in server components, OG images generate from JSX, sitemaps and robots files are typed conventions, and streaming with Suspense helps Core Web Vitals almost by default.

But "Next.js handles SEO" is also one of the most repeated half-truths in the ecosystem. The App Router gives you the tools. It doesn't wire them up for you. Misconfigured metadataBase means every canonical URL in your site points to localhost. Missing generateStaticParams means your dynamic pages get crawler-unfriendly 404s during build. A 'use client' boundary in the wrong place ships 200kb of JS that tanks your INP score.

This guide covers every layer of Next.js SEO, with production-ready patterns for each.

Why the App Router Changes the SEO Picture

The Pages Router gave you next/head — a component you dropped into any page to inject tags into <head>. It worked, but it had problems. Tags could be overridden inconsistently. There was no type safety. Canonical URLs were strings you had to build yourself. There was no native OG image story.

The App Router replaces next/head with the Metadata API: a typed, composable system where each layout.tsx and page.tsx exports either a static metadata object or a generateMetadata async function. Next.js merges these down the layout tree, with inner layouts and pages overriding outer ones. The result is predictable, colocated, and type-safe.

What this means in practice:

  • title.template in your root layout propagates to every page automatically — no wrapper components needed.
  • metadataBase sets the base URL once, and every relative URL in your metadata becomes absolute.
  • metadata.alternates.canonical handles canonical tags without a separate component.
  • metadata.openGraph and metadata.twitter generate all the social meta tags from one object.
  • The opengraph-image.tsx file convention generates OG images from JSX using next/og — per-page, at build time.

For Pages Router projects: you can still use next/head and it still works. But the Metadata API is not available in the Pages Router. Migration to the App Router is the path to the full feature set.

The Six Areas a Next.js Developer Needs to Get Right

1. The Metadata API

Every page needs title, description, canonical URL, and Open Graph tags. The App Router Metadata API handles all of these through a single typed export. The critical things to get right: metadataBase (without it, relative URLs break), title.template (for consistent titling across the site), and generateMetadata for dynamic pages where title and description come from a database or CMS.

The full production pattern — including typed generateMetadata, metadataBase, title.template, and robots — is covered in Next.js App Router Metadata API: The Complete SEO Setup.

2. Dynamic OG Images

Open Graph images are the thumbnail that appears when someone shares your URL on Slack, Twitter, or LinkedIn. Generic images get ignored. Relevant, per-page images get clicks.

next/og generates these images from JSX using Satori under the hood — your component renders to a PNG at build time (or on-demand). The file convention is opengraph-image.tsx colocated with your page.tsx. You get full access to the route segment's data, so you can generate images with the actual post title, author, and date.

The patterns for fonts, external data, and static-versus-runtime tradeoffs are in Next.js Dynamic OG Images with ImageResponse.

3. Sitemap and Robots

Search engines need to know what pages exist and which ones they're allowed to crawl. The App Router gives you app/sitemap.ts and app/robots.ts as file conventions — each exports a typed function that Next.js serves at /sitemap.xml and /robots.txt respectively.

The sitemap convention supports dynamic entries: you can query your database at build time and return an array of URL objects, each with lastModified, changeFrequency, and priority. For large sites, you can split into multiple sitemaps with a sitemap index.

The full production pattern is in Next.js Sitemap and Robots.txt with the App Router.

4. Canonical URLs

Canonical tags tell Google which URL is the "official" version of a page — critical for avoiding duplicate content penalties from pagination, query string variations, or HTTP/HTTPS/www inconsistencies.

In the App Router, canonicals go through metadata.alternates.canonical. Paired with metadataBase, you can use relative URLs everywhere and Next.js makes them absolute. The tricky part is dynamic pages — you need to set the canonical in generateMetadata using the route params.

Edge cases (trailing slashes, hreflang, multi-locale sites) are covered in Next.js Canonical URLs: The metadata.alternates Pattern.

5. Structured Data (JSON-LD)

The Metadata API doesn't cover structured data. JSON-LD lives in a <script type="application/ld+json"> tag in the page head, and you have to put it there yourself. The right pattern is a server component that renders a <Script> tag with dangerouslySetInnerHTML — this keeps the JSON-LD out of client bundles and gives you full TypeScript type safety over your schema objects.

The schema-dts package provides TypeScript types for every schema.org type. Combined with a small helper function, you get type-safe JSON-LD generation for Article, FAQ, BreadcrumbList, and any other schema you need.

The full pattern is in Next.js Structured Data: The Type-Safe JSON-LD Pattern.

6. Core Web Vitals

Next.js gives you a strong CWV baseline: next/image handles responsive sizes and WebP conversion automatically, Server Components reduce client JavaScript significantly, next/font eliminates layout shift from font swaps, and streaming with Suspense improves perceived performance on slow connections.

The gaps are where developers trip up: 'use client' boundaries that ship large third-party libraries, event handlers that block the main thread and kill INP scores, and hero images that are technically "above the fold" in the source but below the fold in the viewport on mobile.

The full optimization workflow — including the specific gotchas and how to diagnose them — is in Next.js Core Web Vitals: Native Optimizations and Where They Fall Short.

App Router vs. Pages Router: The SEO Differences

If you're maintaining a Pages Router project or migrating incrementally, here's what changes:

CapabilityPages RouterApp Router
Meta tagsnext/head componentmetadata export / generateMetadata
OG imagesManual <meta> tags, external serviceopengraph-image.tsx convention, next/og
SitemapManual API route or next-sitemap packageapp/sitemap.ts built-in convention
Robots.txtStatic file in /public or API routeapp/robots.ts built-in convention
Canonical URLsManual <link rel="canonical"> in next/headmetadata.alternates.canonical
JSON-LD<Script> in next/head<Script> in Server Component
Title templatesManual string interpolationtitle.template in root layout
Metadata inheritanceNo inheritance — each page manages its ownLayout tree inheritance with override

The Pages Router is not going away. Next.js continues to support it. But for new projects, the App Router is unambiguously the right choice for SEO — the metadata API alone eliminates a category of bugs that were common in Pages Router apps.

The Incremental Migration Path

If you have an existing Pages Router app and want the App Router's SEO capabilities, Next.js supports running both routers in parallel. You can adopt App Router pages incrementally:

  1. Start with app/layout.tsx and move your root metadata there (replacing the _document.tsx <Head> tags).
  2. Migrate your highest-traffic pages first — these benefit most from the improved metadata and OG image story.
  3. Add app/sitemap.ts and app/robots.ts — these work even if the rest of your app is still in the Pages Router.
  4. Migrate remaining pages when it makes sense.

The incremental approach lets you ship SEO improvements without a big-bang rewrite.

Auditing Your Next.js Site with RankCrab

RankCrab is built on Next.js — so when we say the patterns in this cluster are production-ready, we mean we run them ourselves.

The 80-check audit catches the issues that slip through even when you think you've handled everything: missing metadataBase that corrupts canonical URLs, OG images that exceed Twitter's file size limit, structured data with required fields missing, and pages where noindex accidentally leaked from a staging environment.

The rank tracker tells you whether the SEO work is moving the needle. Technical correctness is necessary but not sufficient — you need to know which keywords are responding.

If you're starting a new Next.js project or auditing an existing one, run it through RankCrab before you ship. The metadata issues especially tend to be invisible until you share a URL and see a broken preview card.

What's Covered in This Cluster

Ship optimized content this afternoon.

7-day trial. $29 when it converts. Cancel from the dashboard the second it stops earning its keep.