DomainLens

Guides

Next.js SEO Checklist: Metadata, Rendering and Routing

Next.js does most of SEO correctly by default. The failures come from choosing the wrong rendering mode for a route and from metadata that runs on the client.

Prüfe deine Website vor den Fixes

Starte ein frisches DomainLens-Audit und nutze den Report als Prioritätenliste.

Kostenloses SEO-Audit starten

Rendering mode decides everything else

Next.js can render a route statically at build time, on the server per request, or entirely on the client. The first two produce complete HTML and behave like any server-rendered site. The third produces an empty shell and inherits every risk of client-side rendering.

The practical rule: any route that should rank must render on the server or be statically generated. Client-only rendering is for authenticated dashboards, not for public content.

ModeWhen to useSEO risk
Static (SSG / ISR)Content that changes rarelyNone
Server (SSR)Per-request or personalised contentNone
Client onlyAuthenticated app routesHigh — empty first pass
Partial prerenderMixed static shell, dynamic partsLow, if the shell has content

Metadata must render on the server

The App Router's metadata export and generateMetadata function both run server-side, which is what makes them safe. Setting titles or canonical tags from a client component means they exist only after hydration, which is too late for the first indexing pass.

This is the most common Next.js SEO defect, and it survives review because the tags are unquestionably present when you inspect the page in a browser.

App Router metadata, done server-side
// app/blog/[slug]/page.tsx
export async function generateMetadata({ params }) {
  const post = await getPost(params.slug);

  return {
    title: post.title,
    description: post.excerpt,
    alternates: { canonical: `https://example.com/blog/${params.slug}` },
    openGraph: { title: post.title, images: [post.image] },
  };
}

// Pages Router equivalent uses next/head inside the page
// component — also server-rendered, and also fine.

The checklist

The canonical point catches people out: Next.js handles almost everything and does not emit a canonical tag on its own. A site can be perfectly rendered and still have every parameter variant competing.

  1. 1Confirm every public route renders on the server — fetch it with curl and read the HTML.
  2. 2Set metadata through the metadata export or generateMetadata, never from a client component.
  3. 3Declare a canonical for every page; Next.js does not add one automatically.
  4. 4Use the not-found convention so unmatched routes return a real 404 rather than a 200 shell.
  5. 5Generate sitemap.ts and robots.ts from your content rather than maintaining static files.
  6. 6Use next/link for internal navigation — it renders a real anchor with an href.
  7. 7Use next/image with explicit dimensions, and set priority on the LCP image so it is not lazy-loaded.

The 404 that is not a 404

A catch-all route rendering a not-found component returns 200 unless the framework convention is used. That produces soft 404s at every typo and stale link, and on a large site the count is unbounded. The App Router's not-found file and the notFound() helper set the status correctly; a hand-rolled fallback usually does not. Verify with curl rather than by looking at the page. See soft 404 errors .

Performance defaults worth keeping

The priority flag on the hero image is the single most common Next.js performance mistake, because next/image lazy-loads by default and that default is wrong for exactly one image on each page. See lazy loading images .

  • next/image handles sizing, format negotiation and lazy loading — but set priority on the hero, or it lazy-loads your LCP element.
  • next/font removes the render-blocking font request, which is a free CLS and LCP improvement.
  • Static generation with ISR gives you cached HTML with periodic freshness, which fixes TTFB almost entirely.
  • Route-level code splitting is automatic; adding manual dynamic imports on top often makes interaction worse.

How DomainLens contributes

DomainLens reads the served HTML, so a route that renders on the client or a metadata export that quietly moved to a client component shows up as missing tags rather than as a mystery. See JavaScript SEO for how rendering works and the React checklist for the framework underneath.

Is Next.js good for SEO?
Yes, when routes render on the server or are statically generated. Client-only rendering in Next.js carries the same risks as any SPA.
Does Next.js add canonical tags automatically?
No. Set them through the alternates field in your metadata, or every URL variant competes with itself.
Why does my Next.js 404 page return 200?
A component rendering a not-found message does not set the status. Use the not-found convention or call notFound() so the server sends 404.
Should I use next/image?
Yes, with explicit dimensions. Set priority on the LCP image, since the default lazy-loading behaviour is wrong for it.

Ähnliche Ressourcen