2026-08-03 · Jack Stovell
How to add llms.txt to a Next.js site
Put a plain-text file at public/llms.txt and Next.js serves it at yourdomain.com/llms.txt — no configuration, and it works identically in the App Router and the Pages Router. If the file should track content that changes often, use a route handler at app/llms.txt/route.ts that returns text/plain instead. Next.js is the easy case: you control the server, so there is no platform workaround to learn.
Where does llms.txt go in Next.js?
In the public directory at the project root. Everything in public is served from your site's root path as-is, on every hosting target and in both routers:
your-project/
app/ (or pages/)
public/
llms.txt -> served at https://yourdomain.com/llms.txtThe file itself is plain markdown: an H1 with your name or business, a short blockquote summary, then your most important URLs with one line of context each.
# Jane Smith — Freelance Data Engineer
> Independent data engineer in Bristol, UK. I build reporting
> pipelines for mid-size retailers and write about the trade.
## Key pages
- [About](https://example.com/about): who I am, experience, how I work
- [Writing](https://example.com/blog): selected posts on data pipelines
- [Contact](https://example.com/contact): email and booking linkCommit, deploy, then verify with curl -i https://yourdomain.com/llms.txt — you want an HTTP 200 and a text content type. What to write and why is covered in our full llms.txt guide. The short honest version: llms.txt is a proposed convention with early, unproven adoption — crawlers request it (we see the hits in our logs), but no major AI vendor documents using it for answers. Worth shipping because it costs nothing, not because anyone has promised to read it.
When would you generate it dynamically instead?
When the file should stay in step with content you don't hand-edit — a CMS-driven blog, docs, a changing catalogue. A route handler owns the same URL and builds the file from your data source, so it can never drift stale:
// app/llms.txt/route.ts
export async function GET() {
// Replace with a fetch from your CMS or database.
const posts = [
{ title: "Migrating a warehouse without downtime", url: "https://example.com/blog/warehouse-migration" },
{ title: "Choosing boring pipeline tools", url: "https://example.com/blog/boring-tools" },
];
const body = [
"# Jane Smith — Freelance Data Engineer",
"",
"> Independent data engineer in Bristol, UK.",
"",
"## Key pages",
"",
"- [About](https://example.com/about): who I am and how I work",
...posts.map((p) => `- [${p.title}](${p.url})`),
"- [Contact](https://example.com/contact): email and booking link",
"",
].join("\n");
return new Response(body, {
headers: { "content-type": "text/plain; charset=utf-8" },
});
}Folder names containing a dot are valid route segments, so app/llms.txt/route.ts maps cleanly to /llms.txt. Use the static file or the route handler, not both — give the path one owner. On the Pages Router, either keep the static file or pair an API route with a rewrite in next.config.js; the App Router version above is simpler.
One honest caveat on caching: route handler defaults have changed between recent Next.js majors, so if freshness matters, set your route's caching behaviour explicitly and confirm with a fresh curl after deploy rather than trusting the default.
Two adjacent things worth checking while you're here. First, robots.txt: the llms.txt file achieves nothing if your robots rules turn AI crawlers away — the user agents to check are listed here. Second, rendering: if your pages are client-rendered shells, fixing that matters far more than any index file, and Next.js gives you server rendering for free — semantic, server-rendered HTML is what AI actually reads.
A live, generated-per-person example of the format is at i.hilyt.it/jack/llm.txt, and our free AI visibility checker will test your llms.txt, robots stance and rendering in one pass. What the file won't do: earn citations by itself. It removes one reason to be skipped; the rest is retrieval, ranking and model behaviour.
Related guides
- What is llms.txt — and how to write one (with a full example)
- Semantic HTML for AI readability: the markup that makes you legible
- AI crawler user agents: the full list (GPTBot, ClaudeBot, PerplexityBot and more)