Add a spec-compliant /llms.txt to your Astro site. Static file, API route, or a tiny integration that builds from your content collections.
Astro is docs-first: Starlight sites, blogs, and marketing pages usually have a well-structured content collection already. An API route at src/pages/llms.txt.ts can iterate getCollection() and emit a spec-compliant file that stays in sync with your posts automatically.
For fully static sites, add export const prerender = true and the route is compiled into a static asset at build time. There is no runtime cost, and the output works with adapter-cloudflare, adapter-vercel, adapter-netlify, and adapter-node.
Pick whichever fits your stack. For most teams the module or a static file is enough; reach for the dynamic route when you need request-time content.
Drop a file at public/llms.txt. No build step, no server logic.
```md # My Astro Project > A short summary of what this project does and who it is for. ## Docs - [Getting Started](https://example.com/docs/getting-started): Quick setup guide - [Guides](https://example.com/guides): How-to guides ## Blog - [Latest Posts](https://example.com/blog): Recent posts ```
Generate at request time from a CMS, MDX collection, or database. Handler at src/pages/llms.txt.ts.
```ts
import type { APIRoute } from 'astro'
import { getCollection } from 'astro:content'
export const prerender = true
export const GET: APIRoute = async ({ site }) => {
const docs = await getCollection('docs')
const origin = site?.origin ?? 'https://example.com'
const lines = ['# My Astro Project', '', '> Short summary.', '', '## Docs']
for (const entry of docs) {
const url = new URL(`/docs/${entry.slug}`, origin).href
lines.push(`- [${entry.data.title}](${url}): ${entry.data.description ?? ''}`)
}
return new Response(lines.join('\n'), {
headers: { 'Content-Type': 'text/plain; charset=utf-8' },
})
}
```Astro API route. Prerender is true by default in static output — leave it for static, or switch to output: "server" in astro.config.mjs for request-time generation.
Claude Code, Cursor, and Codex increasingly request markdown via the Accept: text/markdown header. Pairing your llms.txt with per-page markdown responses makes your whole site legible to agents, not just the index.
Generate llms.txt from your URL or browse the llms.txt directory for real examples.
Yes. Starlight uses Astro content collections under the hood, so the src/pages/llms.txt.ts example above works unchanged. Iterate the "docs" collection, emit one link per entry, and you get an llms.txt that mirrors your Starlight sidebar.
public/llms.txt is the fastest path for a hand-curated file. src/pages/llms.txt.ts is the better choice when your content lives in collections — the route regenerates the file every deploy with zero manual upkeep.
Yes. Remove export const prerender = true and the route runs on every request. Cache it with Cache-Control or at the CDN layer if you don't want to hit your content layer per request.
Duplicate the endpoint as src/pages/llms-full.txt.ts and inline the full rendered body of each entry instead of emitting a link. Astro's content render() returns the full HTML or MDX, which you can pipe through an HTML-to-Markdown converter like mdream.