Next.js robots.txt

Next.js gives you two clean ways to ship robots.txt: a static file in public/, or a typed app/robots.ts metadata route that generates it programmatically. Here's when to use each, with working code.

RSRobots.txt Studio Editorial Updated June 8, 2026 Reviewed against Google Search Central and RFC 9309

Two ways to serve robots.txt

A static public/robots.txt is simplest and best when your rules never change. The App Router's app/robots.ts (a MetadataRoute.Robots export) is better when rules depend on the environment, a CMS, or your base URL — it's typed, testable, and keeps the sitemap URL in sync with the rest of your metadata.

ApproachUse when
public/robots.txtRules are static and simple
app/robots.tsRules are dynamic, env-aware, or generated

The app/robots.ts metadata route

Export a default function returning a MetadataRoute.Robots object. Next.js serves it at /robots.txt automatically. This is the approach this very site uses.

app/robots.ts
import type { MetadataRoute } from 'next'

export default function robots(): MetadataRoute.Robots {
  return {
    rules: [
      { userAgent: '*', allow: '/', disallow: ['/dev', '/api/'] },
      { userAgent: ['GPTBot', 'CCBot', 'Google-Extended'], disallow: '/' },
    ],
    sitemap: 'https://example.com/sitemap.xml',
    host: 'https://example.com',
  }
}
Robots.txt ValidatorValidate your file

The static public/robots.txt

Drop a plain file at public/robots.txt and Next.js serves it verbatim at /robots.txt:

public/robots.txt
User-agent: *
Allow: /
Disallow: /api/

Sitemap: https://example.com/sitemap.xml

Don't do both

If both public/robots.txt and app/robots.ts exist, the static file wins and your route is ignored. Pick one.

Block crawlers on preview/staging deploys

A major advantage of app/robots.ts: you can return Disallow: / on preview deployments and the real rules in production, so staging never gets indexed.

Keep preview deploys out of search
export default function robots(): MetadataRoute.Robots {
  const isProd = process.env.VERCEL_ENV === 'production'
  return isProd
    ? { rules: [{ userAgent: '*', allow: '/' }], sitemap: 'https://example.com/sitemap.xml' }
    : { rules: [{ userAgent: '*', disallow: '/' }] }
}

Common Next.js mistakes

  • Shipping a dev Disallow: / to production

    If you env-gate robots.txt, double-check the production branch returns the allow rules.

  • Having both a static file and robots.ts

    The static public file silently overrides the route. Keep only one.

  • Hardcoding the wrong host

    Use an absolute https sitemap URL that matches your canonical domain.

  • Blocking /_next/static

    That holds your JS and CSS chunks. Blocking it breaks rendering for crawlers.

Frequently asked questions
How do I add robots.txt to a Next.js app?

Either place a static file at public/robots.txt, or add app/robots.ts exporting a default function that returns a MetadataRoute.Robots object. Next.js serves either at /robots.txt. Use robots.ts when the rules need to be dynamic.

Should I use app/robots.ts or a static file?

Use a static public/robots.txt for simple, unchanging rules. Use app/robots.ts when rules depend on the environment (e.g. blocking preview deploys), a CMS, or your base URL — it's typed and generated at build time.

Why is my Next.js robots.txt not updating?

A static public/robots.txt overrides app/robots.ts. If you have both, the route is ignored. Remove the static file, or edit the file that's actually being served — confirm with the Analyzer.

How do I block AI crawlers in Next.js?

In app/robots.ts, add a rule with userAgent set to an array like ['GPTBot', 'CCBot', 'Google-Extended'] and disallow '/'. In a static file, add the equivalent User-agent groups.

Robots.txt Analyzer

Fetch and audit any site's live robots.txt in one report.

Analyze a site
Related resources
Next uprobots.txt vs noindex
RS

Robots.txt Studio Editorial · Technical SEO & crawling

We build robots.txt tooling and parse thousands of real-world files. Guides are written by practitioners and reviewed against the Google and RFC 9309 specifications.