Robots.txt for Next.js — App Router & Pages Router Examples
Production-ready robots.txt for Next.js. Static and dynamic generation with the App Router metadata API, Pages Router examples, and what NOT to block.
Two ways to ship robots.txt with Next.js: a static file in public/, or a dynamic
robots.ts generated at build time using the App Router metadata API.
Option 1: Static public/robots.txt (simplest)
Drop a file at public/robots.txt and Next.js serves it at /robots.txt. This works for both the App Router and the Pages Router. Use this when your rules don't depend on environment.
# public/robots.txt User-agent: * Allow: / Disallow: /api/ Sitemap: https://yourdomain.com/sitemap.xml
Option 2: Dynamic app/robots.ts (App Router)
Since Next.js 13.3, the App Router supports a robots.ts (or .js) file that exports a default function returning a Robots object. Next.js generates the final text file at build time.
// app/robots.ts
import type { MetadataRoute } from 'next'
export default function robots(): MetadataRoute.Robots {
return {
rules: [
{ userAgent: '*', allow: '/', disallow: '/api/' },
{ userAgent: 'GPTBot', disallow: '/' },
{ userAgent: 'ClaudeBot', disallow: '/' },
{ userAgent: 'Google-Extended', disallow: '/' },
],
sitemap: 'https://yourdomain.com/sitemap.xml',
}
} Reference: Next.js Metadata API — robots.
Option 3: Pages Router
The Pages Router has no robots.ts convention. Use the static file approach (public/robots.txt) or write an API route at pages/api/robots.ts and rewrite /robots.txt to it via next.config.js:
// next.config.js
module.exports = {
async rewrites() {
return [
{ source: '/robots.txt', destination: '/api/robots' },
]
},
} Don't Block /_next/
Common mistake: blocking /_next/ in robots.txt. This stops Googlebot from fetching your JavaScript and CSS, and Google needs both to render the page for indexing. Leave /_next/ open. Only consider blocking /api/ if those endpoints have no SEO value.
Conditional Rules per Environment
Block everything on previews so deploy URLs don't get indexed, then loosen on production:
// app/robots.ts
import type { MetadataRoute } from 'next'
export default function robots(): MetadataRoute.Robots {
const isProd = process.env.VERCEL_ENV === 'production'
if (!isProd) {
return { rules: [{ userAgent: '*', disallow: '/' }] }
}
return {
rules: [{ userAgent: '*', allow: '/', disallow: '/api/' }],
sitemap: 'https://yourdomain.com/sitemap.xml',
}
} Internationalized Routes (i18n)
Next.js i18n routes (/en/..., /ja/...) don't need special robots rules — leave them all crawlable and use hreflang tags to tell Google how the locales relate.
Block AI Crawlers
List each AI user-agent on its own block:
User-agent: GPTBot Disallow: / User-agent: ClaudeBot Disallow: / User-agent: anthropic-ai Disallow: / User-agent: Google-Extended Disallow: / User-agent: CCBot Disallow: /
Note: Google-Extended only opts you out of Gemini and Google's AI training. It does not affect Google Search rankings — those use the regular Googlebot user-agent.
Test Your Robots.txt
- Build and start your app:
next build && next start - Open
http://localhost:3000/robots.txtand confirm the file is served. - After deploy, verify
https://yourdomain.com/robots.txtreturns 200 withContent-Type: text/plain. - Test individual rules with the Google Search Console robots.txt tester.
Next.js Robots.txt FAQ
Should I use public/robots.txt or app/robots.ts?
Use the static public/robots.txt for simple, environment-independent rules. Switch to app/robots.ts when you need to compute rules at build time — for example, blocking previews, reading the sitemap URL from an env var, or generating per-locale rules. Both ship the same final file at /robots.txt.
Is it safe to block /_next/?
No. Google must fetch your JS and CSS to render the page during indexing. Blocking /_next/ in robots.txt will degrade or break rendering and hurt your rankings. Leave it open.
Should I block /api/?
If your API routes return JSON or non-page responses, blocking /api/ saves crawl budget and keeps them out of search results. If any API route returns HTML that should be indexed, list it under Allow: instead of disallowing the whole prefix.
Do Vercel preview deployments need a different robots.txt?
Yes — preview URLs should never be indexed. Either return X-Robots-Tag: noindex from middleware on non-production environments, or use the conditional app/robots.ts pattern shown above. A preview indexed by Google can outrank your real production page until it gets removed.
Where does app/robots.ts output the file?
Next.js writes the generated file to the build output and serves it at /robots.txt. You don't manage a physical file in public/; in fact, having both will conflict.
How do I block AI crawlers without affecting Google Search?
Block GPTBot, ClaudeBot, anthropic-ai, Google-Extended and CCBot explicitly. Googlebot is the user-agent that powers Google Search and is separate from Google-Extended, which only powers Gemini and Google's generative AI training.
RELATED TOOLS