Does Next.js support SEO? Yes, and better than a client-only React app, because pages can arrive as complete HTML with their head tags already in place. But the framework only provides the mechanism. Titles, descriptions, canonical URLs, sitemaps and robots rules are still yours to define, and the defaults cover very little. This guide works through the App Router features that matter for search.
Does Next.js support SEO out of the box?
Partly. The Next.js metadata documentation lists two tags that are always added, even when a route defines no metadata: a charset tag and a viewport tag.
That viewport value is the standard responsive setting, which our post on the viewport meta tag explains. Everything else, including the title and description, has to come from your code. A Next.js site with no metadata defined will ship pages without them.

Static metadata and generateMetadata
Next.js offers two ways to define metadata. A static metadata object suits pages whose title and description never change. The generateMetadata function suits pages that depend on data, such as a product or article fetched by slug. Either way, the documentation says “Next.js will automatically generate the relevant <head> tags for your page.”
One constraint matters: both options work only in Server Components. If a page is a Client Component from the top, move the metadata export to a server layout or page and render the interactive part as a child. Set shared values, such as a title template and the site name, once in the root layout, and let individual routes override them.
Plan for missing data too. If generateMetadata fetches a record that no longer exists, the page should return a proper not-found response rather than a page titled “undefined”. That sounds obvious, yet empty and duplicated titles are among the most common problems on data-driven Next.js sites, usually because a fallback was never written. Give every dynamic route a sensible default title and description, and make the canonical URL explicit rather than leaving search engines to guess between trailing-slash, query-string and preview variants of the same page.

Streaming metadata and which bots see it
On dynamic pages, Next.js can stream metadata, sending the page before generateMetadata has finished. That helps perceived speed for people, but some crawlers only read tags inside the head. The documentation says streaming is “disabled for bots and crawlers that expect metadata to be in the <head> tag (e.g. Twitterbot, Slackbot, Bingbot)”, and the list is configurable with the htmlLimitedBots option. Prerendered pages do not stream metadata at all.
In practice, if you rely on a crawler that is not on the default list, add it to htmlLimitedBots and check the raw HTML it receives. Social preview cards are where gaps show first; our post on Open Graph tags covers what those crawlers expect.
| Feature | What Next.js does | What you still decide |
|---|---|---|
| Default tags | Always adds charset and viewport | Title, description, canonical |
metadata object | Generates head tags for static values | The values themselves |
generateMetadata | Generates head tags from data | Fallbacks when data is missing |
| Streaming metadata | Disabled for bots that expect metadata in the head | Extra bots via htmlLimitedBots |
| File conventions | robots.txt, sitemap.xml, opengraph-image, favicon, static or generated | Which URLs to list and which to disallow |

Sitemaps, robots and social images as files
Next.js treats several SEO files as conventions in the app directory: robots.txt, sitemap.xml, opengraph-image and favicon. Each can be a static file you drop in, or code that generates it. A generated sitemap is the better choice for any site whose URLs come from a database or CMS.
List only canonical, indexable URLs, and keep lastModified honest rather than stamping today’s date on everything. Our guide to XML sitemaps covers what search engines do with those fields. A generated robots.ts is useful for one specific job: serving a blanket disallow on preview deployments and a normal file in production, so a staging copy never gets indexed.
The opengraph-image convention works the same way. A static image file sets one preview image for a route segment; a generated one can render a card per page, with the article title drawn in. Social shares do not rank pages, but a missing or broken preview image makes links look neglected wherever they are posted.

How Next.js helps with SEO: rendering choices
The biggest SEO decision in a Next.js project is not metadata. It is how each route renders. Prerendered and server-rendered pages send complete HTML, so crawlers see the content on the first fetch. Content that only appears after client-side JavaScript runs depends on the crawler rendering the page, which some do slowly and some not at all.
Keep the content you want indexed in server-rendered output, and use client components for interaction rather than for loading the main text. Our posts on server-side rendering and SEO and JavaScript SEO cover the trade-offs in depth.

Checking what crawlers actually receive
Do not judge Next.js SEO from the browser’s rendered DOM. Fetch the page as raw HTML, with a command-line request or the view-source option, and confirm the title, description, canonical and Open Graph tags are in the head. Then run URL Inspection in Search Console to see Google’s rendered version.
Repeat the check after upgrades. Framework releases change defaults, and a route that was prerendered can become dynamic after a small code change, such as reading a cookie or a header. Add a simple test to your deployment pipeline that fetches a handful of key URLs and fails if the title or canonical is missing.

One limitation is worth stating. The documentation describes how Next.js generates tags; it cannot tell you how any particular crawler will treat streamed or client-rendered content. Behaviour differs between search engines and social platforms, and changes over time, so the only reliable check is the HTML each crawler receives.
The working setup is straightforward. Define a title template and defaults in the root layout, use generateMetadata for data-driven routes, generate the sitemap from the same source as your pages, and serve robots rules that differ between preview and production. Prerender wherever you can, and keep indexable content out of client-only code. Our strategy archive collects the related technical posts.
Frequently asked questions
Is Next.js good for SEO?
Yes. It can send complete server-rendered HTML with head tags in place. You still have to define titles, descriptions, canonicals and sitemaps yourself.
What meta tags does Next.js add by default?
Two: a charset tag and a viewport tag set to width=device-width, initial-scale=1. Everything else comes from your metadata.
Can I use generateMetadata in a Client Component?
No. Both the metadata object and generateMetadata are supported only in Server Components.
Does streaming metadata hurt SEO?
Next.js disables streaming for bots that expect metadata in the head, such as Twitterbot, Slackbot and Bingbot, and you can extend that list with htmlLimitedBots. Prerendered pages do not stream metadata.
The takeaway Next.js supports SEO well, but only provides the mechanism. Define metadata in Server Components, generate sitemaps and robots rules from code, and keep indexable content server-rendered.

