How to Generate llms.txt and llms-full.txt in Next.js (App Router Guide)
Serving statically hardcoded metadata is no longer sufficient. Modern dynamic web frameworks need to render LLM-ready directories on the fly. Let's look at how to build and cache dynamic llms.txt files in Next.js.
Key Takeaways
- Next.js Route Handlers allow real-time compilation of markdown files.
- Edge caching and Incremental Static Regeneration (ISR) prevent database strain.
- Inlining dynamic content in llms-full.txt saves AI crawler token budgets.
- Proper Content-Type headers prevent browser download prompts.
1. The Architecture of Next.js dynamic routing
Next.js App Router relies on Route Handlers to serve custom formats like plain text, XML, or JSON. Placing an llms.txt file in your public directory works only for static content. When content updates, a static asset requires a full redeploy of the application.
Using a dynamic Route Handler lets you query CMS platforms or local files on the fly. This ensures crawling tools immediately locate newly added reference material. For high performance, we recommend deploying on robust instances like DigitalOcean, which scales easily under crawler spikes.
Next.js AI Ingestion Routing Flow
2. Implementation of app/llms.txt/route.ts
Create a directory path at app/llms.txt and add a route.ts file. This script queries your documentation pages and compiles the main directory index.
import { NextResponse } from 'next/server';
export const revalidate = 86400; // Cache for 24 hours
export async function GET() {
const siteUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://llms-txt.xyz';
// Example fetching dynamic resources
const docs = [
{ title: "Validator Guide", url: `${siteUrl}/how-to-validate-llms-txt` },
{ title: "SEO Benefits", url: `${siteUrl}/llms-txt-seo-benefit` },
{ title: "Shopify Integration", url: `${siteUrl}/llms-txt-shopify` }
];
let output = `# llms-txt.xyz Docs\n`;
output += `> Dynamic documentation index generated for AI agents.\n\n`;
output += `## Core Guides\n`;
docs.forEach(doc => {
output += `- [${doc.title}](${doc.url})\n`;
});
output += `\n## Full Indexes\n`;
output += `- [llms-full.txt](${siteUrl}/llms-full.txt): Complete full-text documentation database.\n`;
return new NextResponse(output, {
headers: {
'Content-Type': 'text/plain; charset=utf-8',
'Cache-Control': 'public, s-maxage=86400, stale-while-revalidate=3600'
}
});
}
3. Dynamic llms-full.txt Compilation
The standard recommends linking to a full-text representation at llms-full.txt. This contains inlined markdown descriptions of every linked page. To learn more about this format, check out our guide on llms-full.txt explained.
Let's look at the differences between the two endpoints:
| Specification | llms.txt | llms-full.txt |
|---|---|---|
| Primary Content | Concise list of hyperlinks | Inlined raw markdown body |
| Average File Size | 1 - 5 KB | 50 - 500 KB |
| Crawl Purpose | Discovery & mapping | Direct ingestion & RAG context |
To automate compilation, you can write script controllers that read local MDX assets, strip YAML frontmatter, and output clean content buffers. You can explore how to set this up in our guide on generating llms-full.txt programmatically.
4. Testing Your Implementation
After deploying your Next.js route, verify that the served format is correct. Relative URL formats or lack of headers can cause crawler parsers to fail. You can debug your routes using our free llms.txt validator tool to check for formatting compliant with standard parameters.
Frequently Asked Questions
Route Handlers generate the list dynamically, ensuring any new documentation pages or posts are indexed immediately by AI crawlers without redeploying.
Yes, Next.js Route Handlers support on-demand rendering, letting you fetch live page schemas from database backends or headless CMS platforms.
Set custom Cache-Control headers in the NextResponse object, such as s-maxage=86400, to prevent hammering your backend for every crawl.
Use npm libraries like Turndown to convert raw HTML fields or leverage external scraper platforms like the Firecrawl API.
No, omit all draft or private pages using database query filters to protect unreleased documentation.
Yes, you can inspect the incoming Request headers inside your Route Handler and restrict access for blocklisted bots.
You can define redirects inside next.config.js or rewrite requests via middleware.ts directly to your dynamic route folder.
Yes, major LLM crawlers query the site root folder /llms.txt. Serving a valid response at this endpoint is critical.
Yes, export a revalidate constant (e.g., export const revalidate = 3600) to combine static rendering speeds with periodic updates.
No. The file itself is served as text/plain. Schema markup is only required on the HTML page hosting this guide.