Complete SEO Guide for Next.js 15: Meta Tags, Structured Data, and Core Web Vitals

David Palacios
5 min read

SEO in a modern web application is less about sprinkling tags and more about how your system behaves at request time. Search engines, crawlers, and social platforms do not “run your app”—they read the output it produces. If that output is inconsistent, late, or disconnected from your routing and data, the system becomes difficult to interpret from the outside.

This guide walks through a setup that has held up in real projects using the Next.js App Router. The goal is not to cover every tactic, but to establish a coherent pipeline: one place where page meaning is defined, one place where it is translated into metadata, and a rendering path that stays predictable.


A practical mental model#

Think of SEO as a request-time pipeline:

  1. A request arrives for a URL
  2. The system resolves what that page represents
  3. Metadata is derived from that representation
  4. HTML is rendered with those signals
  5. External systems interpret the result

If any of those steps are ambiguous or duplicated, inconsistencies appear. The rest of this guide is about removing that ambiguity.


Defining metadata once, not everywhere#

A common failure mode is scattering metadata across layouts, pages, and helpers. It works until it doesn’t—then you are debugging why previews or canonical URLs don’t match.

A better approach is to define a single typed description of page metadata and reuse it everywhere.

Example: a small SEO builder#

The important part is not the fields, it is that every page goes through the same function.


Wiring it into the App Router#

In Next.js App Router, metadata is produced via generateMetadata. The page should only provide what is unique, and delegate the rest.

Example: route-level metadata#

This keeps the contract simple:

  • the route provides content context
  • the SEO layer provides representation

Rendering structured data (JSON-LD)#

Structured data should mirror what a user sees on the page. It is not a place to exaggerate capabilities—it is a way to clarify content type.

Example: BlogPosting JSON-LD#

Use this only when it reflects real content. If your page is not an article, do not pretend it is one.


Canonical URLs and routing alignment#

Canonical URLs are simple in concept but easy to get wrong when routing evolves.

A reliable rule:

The canonical URL should be derived from the same function that generates your routes.

If your app builds URLs dynamically (e.g., slugs, filters), centralize that logic and reuse it for:

  • links in the UI
  • canonical URLs
  • sitemap entries

This avoids drift.


Generating a sitemap from the same data source#

Your sitemap should not be a separate, hand-maintained artifact. It should be generated from the same source that drives your UI.

Example: dynamic sitemap#

If your blog index and your sitemap read from the same data, they cannot drift apart.


robots.txt as a policy, not an afterthought#

Robots configuration should reflect how your application is meant to be consumed.

Example:#

If you have draft routes, admin panels, or preview paths, this is where they should be explicitly excluded.


Core Web Vitals: decisions that actually move the needle#

Performance is part of SEO because it affects how users experience your pages.

In App Router projects, the gains usually come from a few concrete choices:

  • Render as much as possible on the server for content-heavy pages
  • Reserve layout space for images and fonts to avoid shifts
  • Avoid unnecessary client bundles on first load

Example: optimized image usage#

This ensures the browser knows dimensions ahead of time, reducing layout shifts.


A simple validation checklist#

Before publishing a page, check the system, not just the UI:

  • Does the canonical URL match the actual route?
  • Does the Open Graph image render correctly in preview tools?
  • Does the structured data match visible content?
  • Is the page included in the sitemap?
  • Are there any unintended noindex directives?

These checks are less about perfection and more about consistency.


What this approach changes#

When SEO is treated as part of system design:

  • metadata becomes predictable
  • refactors stop breaking external signals
  • onboarding becomes easier (there is one clear pipeline)
  • debugging becomes faster (fewer hidden paths)

The system does not become more complex.

It becomes more coherent.


SEO is often framed as visibility.

In practice, it is about how clearly your system explains itself to other systems.

When your application:

  • defines page meaning once
  • translates it consistently
  • and renders it predictably

search engines and platforms can trust it.

And once that trust is established, everything else—indexing, previews, ranking signals—starts working with you instead of against you.