# How to make your Next.js site appear in ChatGPT (and any LLM)

> Source: <https://dev.to/gustavo_garcia_dev/how-to-make-your-nextjs-site-appear-in-chatgpt-and-any-llm-3mph>
> Published: 2026-08-03 02:11:43+00:00

You blocked `GPTBot`

in `robots.txt`

to keep your content out of training runs — and then wondered why ChatGPT Search never cites your docs. Those are **different systems**. OpenAI’s own crawler docs say each bot is independent: allowing `OAI-SearchBot`

keeps you eligible for ChatGPT search answers while disallowing `GPTBot`

opts you out of foundation-model training.

This article is a Next.js App Router playbook for **Generative Engine Optimization (GEO)**: how answer engines discover pages, which user-agents actually matter, how to configure `robots.ts`

and sitemaps, how to keep HTML crawlable, and what `llms.txt`

does — and does not — guarantee.

Treat “appearing in an LLM” as three separate pipelines:

| Pipeline | What it does | Typical bots / tokens |
|---|---|---|
Training crawl |
Collects public pages that may enter future model training |
`GPTBot` , `ClaudeBot` , `Google-Extended` (token), Common Crawl’s `CCBot`
|
Search / answer index |
Builds or refreshes retrieval so answers can cite your URLs |
`OAI-SearchBot` , `Claude-SearchBot` , `PerplexityBot` , classic `Googlebot` / `Bingbot` (and partners) |
User-triggered fetch |
Downloads a specific URL because a human asked for it (or pasted a link) |
`ChatGPT-User` , `Claude-User` , `Perplexity-User`
|

Blocking the training bot does **not** automatically block the search bot. OpenAI states this explicitly for `GPTBot`

vs `OAI-SearchBot`

. Anthropic documents the same split for `ClaudeBot`

, `Claude-SearchBot`

, and `Claude-User`

. Perplexity documents `PerplexityBot`

for search indexing and `Perplexity-User`

for live fetches.

ChatGPT Search can also partner with third-party search providers. OpenAI’s help center documents that rewritten queries may be sent to partners such as **Bing** (and others listed in that article). Independently, OpenAI recommends allowing ** OAI-SearchBot** if you want to appear in ChatGPT search answers. Practical implication: keep search bots allowed

From [OpenAI’s crawler overview](https://developers.openai.com/api/docs/bots):

Used to surface websites in ChatGPT’s search features. Sites opted out of `OAI-SearchBot`

**will not be shown in ChatGPT search answers**, though they can still appear as plain navigational links. OpenAI recommends allowing it in `robots.txt`

and permitting its [published IP ranges](https://openai.com/searchbot.json). Changes can take about **24 hours** to propagate.

Crawls content that may be used to train generative foundation models. Disallowing `GPTBot`

signals that content should not be used for that training. It does **not** control ChatGPT Search eligibility.

Used when ChatGPT or Custom GPTs fetch a page because of a user action. OpenAI notes it is **not** used for automatic web crawling, **not** used to decide Search inclusion, and that **robots.txt rules may not apply** because the fetch is user-initiated. Manage Search with `OAI-SearchBot`

; treat `ChatGPT-User`

as a separate live-fetch channel.

Only visits pages submitted as ads on ChatGPT; not used to train foundation models. Relevant if you run ChatGPT ads — ignore it for organic GEO.

A common, defensible policy for content sites that want citations but not training:

```
User-agent: OAI-SearchBot
Allow: /

User-agent: GPTBot
Disallow: /
```

[Anthropic’s help center](https://support.claude.com/en/articles/8896518-does-anthropic-crawl-data-from-the-web-and-how-can-site-owners-block-the-crawler) (updated April 2026) defines three bots:

`ClaudeBot`

`Claude-SearchBot`

`Claude-User`

Anthropic honors `robots.txt`

(including non-standard `Crawl-delay`

) and warns that **IP-blocking alone is unreliable** because it can prevent the bot from reading your `robots.txt`

.

[Perplexity’s crawler docs](https://docs.perplexity.ai/docs/resources/perplexity-crawlers) recommend allowing ** PerplexityBot** so your site can appear in Perplexity search results.

`Perplexity-User`

`perplexitybot.json`

/ `perplexity-user.json`

) — robots.txt alone is not enough when the edge drops the request.[ Google-Extended](https://developers.google.com/crawling/docs/crawlers-fetchers/google-common-crawlers) is a

Important trade-off: for OpenAI you can allow search and disallow training separately. For Google, `Google-Extended`

covers **both** Gemini training and Gemini grounding. Allow it if you want Gemini apps to ground on your content; disallow it if you want to opt out of those Gemini uses (Search itself stays separate via `Googlebot`

).

`app/robots.ts`

App Router can generate `/robots.txt`

from a typed file. Official docs: [robots.txt file convention](https://nextjs.org/docs/app/api-reference/file-conventions/metadata/robots).

Example that keeps **search/citation** bots allowed, optionally opts out of **training**, fences private routes, and advertises the sitemap:

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

const SITE = 'https://example.com'

export default function robots(): MetadataRoute.Robots {
  return {
    rules: [
      {
        userAgent: '*',
        allow: '/',
        disallow: ['/api/', '/admin/', '/drafts/'],
      },
      // ChatGPT Search + live fetch
      { userAgent: 'OAI-SearchBot', allow: '/' },
      { userAgent: 'ChatGPT-User', allow: '/' },
      // Training opt-out (optional — remove this rule to allow training)
      { userAgent: 'GPTBot', disallow: '/' },
      // Claude
      { userAgent: 'Claude-SearchBot', allow: '/' },
      { userAgent: 'Claude-User', allow: '/' },
      { userAgent: 'ClaudeBot', disallow: '/' },
      // Perplexity
      { userAgent: 'PerplexityBot', allow: '/' },
      { userAgent: 'Perplexity-User', allow: '/' },
      // Gemini grounding/training token (allow if you want Gemini apps to use you)
      { userAgent: 'Google-Extended', allow: '/' },
    ],
    sitemap: `${SITE}/sitemap.xml`,
    host: SITE,
  }
}
```

After deploy, open `https://your-domain/robots.txt`

and confirm the groups look right. Spoofed user-agents exist — for verification, OpenAI and Perplexity publish IP range JSON files; Anthropic currently points publishers at robots.txt rather than relying on IP blocks.

Crawlers need URLs to discover. Next.js can generate `/sitemap.xml`

from `app/sitemap.ts`

([docs](https://nextjs.org/docs/app/api-reference/file-conventions/metadata/sitemap)):

``` python
// app/sitemap.ts
import type { MetadataRoute } from 'next'

export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
  const posts = await getPublishedPosts() // your data layer

  return [
    { url: 'https://example.com', lastModified: new Date(), priority: 1 },
    ...posts.map((p) => ({
      url: `https://example.com/blog/${p.slug}`,
      lastModified: p.updatedAt ?? p.publishedAt,
      changeFrequency: 'monthly' as const,
      priority: 0.7,
    })),
  ]
}
```

Then:

If ChatGPT Search partners with Bing for some queries, a healthy Bing index is still cheap insurance. A healthy Google index still matters for Google Search, AI Overviews / AI Mode, and anything that grounds on Google’s index.

Answer engines and classic crawlers are more reliable when the **important prose is in the first HTML response**. App Router Server Components and SSR help; shipping an empty shell that only fills after client JavaScript is a classic way to look invisible.

Practical checklist for Next.js:

`<title>`

, meta description, and Open Graph tags via the Metadata API — they travel with the document.`alternates.languages`

in the sitemap when you ship locales.`200`

responses for public pages — timeouts and soft 404s waste crawl budget.Structured data (JSON-LD for `Article`

, `FAQPage`

, `Organization`

, etc.) does not replace good prose, but clear headings, short definitional paragraphs, tables, and FAQ sections match how Bing’s own GEO guidance describes content that is easier to cite accurately.

Technical access is necessary but not sufficient. Pages that get cited tend to:

`##`

/ `###`

headings that match how people ask questionsYou do not need a new CMS. You need pages that are **the best extractable answer** for a specific intent.

`llms.txt`

: useful map, not a ranking switch
Jeremy Howard’s [llms.txt proposal](https://llmstxt.org/) suggests a Markdown file at `/llms.txt`

: site name as `#`

heading, a short `>`

summary, then `##`

sections with curated absolute links. Optional companion files (for example full concatenated context) exist in the ecosystem. Docs platforms (and many agent workflows) already use this pattern.

What it is **not**: a formal standard enforced by OpenAI, Google, or Anthropic for citation ranking. It does not replace `robots.txt`

. It cannot block crawlers. Treat it as a **curated table of contents** for agents and humans who fetch `/llms.txt`

on demand — especially documentation sites — not as a guaranteed ChatGPT ranking lever.

In Next.js you can start with `public/llms.txt`

, or generate it from a Route Handler:

``` js
// app/llms.txt/route.ts
export function GET() {
  const body = `# Acme Docs
> Official documentation for the Acme API and SDKs.

## Docs
- [Quick start](https://example.com/docs/quickstart.md): Install and make your first request
- [Auth](https://example.com/docs/auth.md): API keys and OAuth

## Optional
- [Changelog](https://example.com/changelog): Release history
`

  return new Response(body, {
    headers: {
      'Content-Type': 'text/plain; charset=utf-8',
      'Cache-Control': 'public, max-age=3600',
    },
  })
}
```

If you also serve Markdown mirrors of key pages (the proposal’s `.md`

suffix idea), agents get cleaner context than parsing your marketing HTML.

`GPTBot`

and assuming you left ChatGPT Search`OAI-SearchBot`

allowed for Search answers.`robots.txt`

, hostile WAF`curl`

does not show the answer text, many crawlers will not either.`llms.txt`

as access control`Google-Extended`

while expecting Gemini grounding**Invest in GEO when** you publish public expertise (docs, tutorials, comparisons, research) and want referral traffic or brand citation from ChatGPT, Claude, Perplexity, Copilot, or Gemini.

**De-prioritize (or fully opt out) when** the product is private, paywalled, legally sensitive, or you deliberately do not want model/training or answer-engine reuse — then disallow the relevant bots and accept lower AI visibility.

No. Per OpenAI, Search visibility is governed by ** OAI-SearchBot**.

`GPTBot`

is the training-oriented crawler. You can disallow `GPTBot`

and still allow `OAI-SearchBot`

.OpenAI documents third-party search partners (including Bing) **and** its own `OAI-SearchBot`

. Do both: allow `OAI-SearchBot`

and keep a healthy presence in major indexes. Do not rely on a single secondary blog’s claim about exclusive Bing or Google dependency.

`llms.txt`

make ChatGPT cite me?
There is no public commitment from major AI labs that `llms.txt`

controls ChatGPT citation ranking. It is still worth shipping for docs and agent UX. Citations still depend on crawl access, indexability, and content quality.

Not automatically. Decide per pipeline: search/citation vs training vs user fetch. Many content sites allow search bots, allow or disallow training consciously, and keep sensitive paths disallowed for everyone.

No — Server Components and the Metadata / sitemap / robots file conventions are well suited to crawlable HTML. Problems come from client-only rendering patterns, not from App Router itself.

To show up in ChatGPT Search and other LLM answers: **allow the search crawlers**, **do not let your WAF undo robots.txt**, **ship crawlable HTML from Next.js**, **submit sitemaps** (and IndexNow where it helps), and **write pages that answer specific questions clearly**. Optionally add `llms.txt`

as a curated map. Optionally disallow training bots if that is your policy — without confusing them for search bots.

Ship the `OAI-SearchBot`

allow rule this week if it is missing. Everything else compounds on top of being fetchable.
