AI SEO, sometimes called GEO (generative engine optimization), is the practice of making your site readable, quotable and citable by AI answer engines: ChatGPT, Perplexity, Claude and Google AI Overviews. Classic SEO gets you ranked on a results page; AI SEO gets you quoted inside the answer itself. Next.js is well placed for it, because everything AI engines reward (server-rendered HTML, structured data, machine-readable files) maps to a framework feature. Here is the integration we apply, file by file.
What do AI engines actually read?
Three things matter more than anything else. First, most AI crawlers do not execute JavaScript: GPTBot, ClaudeBot and PerplexityBot fetch the raw HTML of a URL, so content that only appears after client-side rendering is close to invisible to them. Second, answer engines extract passages, not pages: a section that opens with a direct, self-contained answer is far easier to lift than one that builds up to its point. Third, sourced and dated claims win. The Princeton GEO study (KDD 2024) measured visibility in generative engine answers and found that adding citations, quotations and statistics raised it by 30 to 40 percent in their benchmark.
Google is the exception worth naming: its own guidance says AI Overviews are rooted in core Search ranking, need no special markup, and are fed by ordinary Googlebot indexing. So for Google you optimize as usual; the structural work below targets the other engines and costs Google nothing.
Open robots.txt to the right crawlers
Each engine has its own bot, and a blocked bot means that engine cannot cite you. In the App Router this is one file, app/robots.ts:
import type { MetadataRoute } from 'next'
export default function robots(): MetadataRoute.Robots {
return {
rules: [
{ userAgent: '*', allow: '/' },
// AI answer engines: allowing them is what makes citation possible.
{ userAgent: ['OAI-SearchBot', 'ClaudeBot', 'PerplexityBot'], allow: '/' },
],
sitemap: 'https://www.example.com/sitemap.xml',
}
}
Know the trade-off before you open the door: allowing these bots permits citation, and for some of them reuse of your content. A common middle ground is to allow the search-and-cite bots listed above while blocking training-only crawlers such as GPTBot or CCBot. Note that Google-Extended controls Gemini training, not AI Overviews: blocking it does not remove you from Google's AI answers.
Serve complete HTML
This is where Next.js earns its keep. Keep the substance of every page in Server Components so the full text ships in the initial HTML response, and prerender with SSG or ISR so the response is fast: crawlers work with timeouts and a slow origin gets sampled, not read. The classic mistake is hiding half the content behind client-only tabs or accordions: a bot that does not run JavaScript never sees pane two. If a section matters, it belongs in the server-rendered markup.
Want your site to be the answer when an AI engine is asked about your market? Describe your stack: a one-page diagnosis within 48 hours.
Get my diagnosis →Structured data engines can parse
JSON-LD gives engines the who, when and what of a page without guessing. In a Server Component, build the object and inline it; the one subtlety is escaping the < character so user data cannot break out of the script tag:
const article = {
'@context': 'https://schema.org',
'@type': 'Article',
headline: post.title,
datePublished: post.publishedAt,
dateModified: post.updatedAt ?? post.publishedAt,
author: { '@type': 'Person', name: post.author },
}
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify(article).replace(/</g, '\u003c'),
}}
/>
The field that pays for itself is dateModified: AI engines weight freshness heavily, and an article that declares a revision date outranks an undated twin in answer selection.
Publish an llms.txt
llms.txt is a proposed convention: a markdown file at the site root that gives AI systems a curated map of what the site is and where its key pages live. Adoption by engines is still uneven, so treat it as a cheap bet rather than a ranking lever. In Next.js it is a route handler, and it can derive from the same data as your sitemap so it never goes stale:
// app/llms.txt/route.ts
export const dynamic = 'force-static'
export function GET() {
const lines = [
'# Example Studio',
'> Web engineering: Next.js, AWS serverless, bilingual sites.',
'',
'## Guides',
...posts.map((p) => `- [${p.title}](https://www.example.com/en/blog/${p.slug})`),
]
return new Response(lines.join('\n'), {
headers: { 'Content-Type': 'text/plain; charset=utf-8' },
})
}
Write so an engine can lift the answer
Structure is the part no config file can do for you. Phrase H2s the way people phrase questions. Open each section with a 40 to 60 word answer that survives being quoted alone. Prefer a table to three paragraphs for any comparison. Date your claims and name your sources inline: the same habits the GEO study measured are the ones that make a passage worth extracting.
The checklist
- Decide which AI bots you allow, and encode it in app/robots.ts.
- Keep page substance in Server Components; prerender with SSG or ISR.
- Ship Article JSON-LD with datePublished and dateModified.
- Add an llms.txt route handler derived from your content data.
- Open sections with self-contained answers; use tables for comparisons.
- Cite sources and date statistics in the body text.
- Re-test with a plain HTTP fetch: what you see there is what the bots see.