Next.js App Router SEO
The Next.js App Router makes server rendering the default and replaces the old next/head approach with a declarative Metadata API. For SEO this is a strong foundation: routes ship populated HTML and metadata in the response, and you express per-route titles, descriptions, and structured data through typed exports rather than imperative head manipulation. This guide covers the App Router’s SEO surface within framework-specific SEO implementations, applying the rendering-strategy decisions in Next’s model.
Prerequisites
- Next.js 13+ using the
app/directory (App Router). - Route segments organized so metadata can be colocated with each page.
- An understanding of the fetch cache and
revalidatefor per-route rendering mode. - Search Console access to verify rendered metadata.
How it breaks
The App Router’s most common SEO regression is marking a layout or page 'use client' at too high a level, which opts whole subtrees out of server metadata and pushes rendering toward the client. Another is putting generateMetadata work behind an uncached, slow fetch so the route’s TTFB balloons and rendering stalls.
Step-by-step fix
-
Export static metadata for fixed routes.
// app/about/page.jsx export const metadata = { title: 'About — Example', description: 'Who we are and what we build.', alternates: { canonical: 'https://example.com/about' }, }; -
Use
generateMetadatafor data-driven routes. Detailed in dynamic metadata with the Next.js Metadata API.// app/products/[id]/page.jsx export async function generateMetadata({ params }) { const product = await getProduct(params.id); return { title: product.name, description: product.summary }; } -
Set the rendering mode per route with the fetch cache.
export const revalidate = 3600; // ISR; 0 = SSR; force-static = SSG -
Keep
'use client'low in the tree so metadata and content stay server-rendered.
Gotchas & edge cases
'use client'on a layout. Opts whole subtrees out of server metadata; push the directive down to leaf interactive components.- Slow uncached fetch in
generateMetadata. Blocks the response; cache or deduplicate the fetch (Next dedupes identicalfetchcalls within a request). - Missing canonical. Set
alternates.canonicalper route to avoid duplicates — see canonical URL management. - JSON-LD placement. Render a
<script type="application/ld+json">in the server component body; it ships in the response.
Validation checklist
Performance & crawl-budget notes
App Router routes render metadata and content on the server, so they index in the first wave and skip the render queue, protecting crawl budget. The fetch cache lets you serve most routes as static or ISR and reserve full SSR for genuinely dynamic ones, keeping server cost proportional to how dynamic each route really is.
Go deeper
- Dynamic metadata with the Next.js Metadata API — generateMetadata, dynamic OG images, and structured data.
Frequently Asked Questions
How does SEO work in the Next.js App Router? The App Router renders on the server by default and exposes a Metadata API: you export a static metadata object or an async generateMetadata function per route segment, and Next renders the resulting tags into the document head in the response. Rendering mode is controlled per route via the fetch cache and route segment config.
Do I need next/head in the App Router? No. next/head is a Pages Router API. In the App Router you use the Metadata API — the metadata export or generateMetadata — instead, which is server-rendered and typed.
Related
- React Router SEO Best Practices — SEO for React routing outside Next.
- CSR, SSG, SSR & ISR Rendering Strategies — the modes the fetch cache expresses.
- Incremental and streaming SSR for SEO — the App Router streams by default.
← Back to Framework-Specific SEO Implementations