<!-- Generated from llms-txt-astro/index.html. The canonical document is the HTML page. -->

- [ Home ](/) 
/
- [ How to create ](/how-to-create/) 
/
- Astro guide            
# llms.txt with Astro

Two approaches: drop a file in public/ for instant deployment, or generate it dynamically from your content collections with a TypeScript endpoint.

Last updated: April 22, 2026

✓ This site runs on Astro

llmtxt.info is itself built with Astro on Cloudflare Pages. The approaches below are exactly
what we use to serve our own  /llms.txt .

## Approach 1, Static file in `public/`

The simplest option. Create a plain text file at `public/llms.txt` in your project root.
Astro copies the entire `public/` directory verbatim to `dist/` during `astro build`, so the file is served at
`/llms.txt` with zero configuration.
static approach, public/llms.txt   
Copy

```
# Place the file at: public/llms.txt
# Astro copies everything in public/ to the output directory as-is.
# Result: served at https://yoursite.com/llms.txt, no code changes needed.

# After deploy, verify:
curl -I https://yoursite.com/llms.txt
# Expected: HTTP/2 200 | Content-Type: text/plain
```

**When to use this:** your content doesn&rsquo;t change often, you want zero build-time
overhead, or you maintain the file manually. Works identically on Cloudflare Pages, Vercel, Netlify,
and any other Astro host.

## Approach 2, TypeScript endpoint with `getCollection()`

Astro matches the double extension `.txt.ts` and treats
`src/pages/llms.txt.ts` as an API endpoint that responds at
`/llms.txt`. In SSG mode (the default), Astro pre-renders it to a static `dist/llms.txt` at build time, no runtime cost.
src/pages/llms.txt.ts   
Copy

```
// src/pages/llms.txt.ts
// Astro treats src/pages/foo.ext.ts as a route for /foo.ext
// In SSG mode (default), it pre-renders to dist/llms.txt at build time.

import type { APIRoute } from 'astro';
import { getCollection } from 'astro:content';

export const GET: APIRoute = async () => {
// Replace 'docs' with your actual content collection name
const docs = await getCollection('docs');

const lines = [
'# My Site',
'',
'> One-sentence description of what this site is about.',
'',
'## Documentation',
'',
...docs
.filter((d) => !d.data.draft)
.sort((a, b) => (a.data.order ?? 999) - (b.data.order ?? 999))
.map((d) => `- [${d.data.title}](https://yoursite.com/${d.slug}/): ${d.data.summary ?? ''}`.trimEnd()),
'',
'## Optional',
'',
'- [Changelog](https://yoursite.com/changelog/): version history.',
];

return new Response(lines.join('\n'), {
headers: { 'Content-Type': 'text/plain; charset=utf-8' },
});
};

```

Key points:

- Replace `'docs'` with your actual collection name from `src/content/config.ts`. 
- Filter out drafts before mapping: `!d.data.draft`. 
- Each line annotation (`: short note`) is optional but strongly recommended , it
gives LLMs context about each page without them having to fetch it. 
- Always set `Content-Type: text/plain; charset=utf-8` in the response.     
⚠ SSR output mode

If you use  output: 'server'  in  astro.config.mjs , the
endpoint runs on every request. For high-traffic deployments, add
export const prerender = true;  at the top of the file to force static pre-rendering even
in server mode.

## Adding `llms-full.txt`

The [llms-full.txt](/llms-full-txt/) companion file inlines the full body of every page,
useful for RAG pipelines and LLM clients that want the entire corpus at once. Create a parallel endpoint:
src/pages/llms-full.txt.ts   
Copy

```
// src/pages/llms-full.txt.ts
// Generates the full-content companion file.
// Each entry gets its full Markdown body inlined, useful for RAG pipelines.

import type { APIRoute } from 'astro';
import { getCollection } from 'astro:content';

export const GET: APIRoute = async () => {
const docs = await getCollection('docs');
const sections: string[] = [];

for (const doc of docs.filter((d) => !d.data.draft)) {
sections.push(
`# ${doc.data.title}`,
'',
`URL: https://yoursite.com/${doc.slug}/`,
'',
doc.body,   // raw Markdown, no HTML, ideal for LLMs (Astro 4+)
'',
'---',
'',
);
}

return new Response(sections.join('\n'), {
headers: { 'Content-Type': 'text/plain; charset=utf-8' },
});
};

```

`doc.body` contains raw Markdown (available since Astro 4), which is ideal for LLMs: no
HTML tags, clean semantic text. For Astro 3, use the
`render()` helper and strip tags with a simple regex.

## Verify after build
verify   
Copy

```
# Build the project
npx astro build

# Check static output (works for both approaches in SSG mode)
cat dist/llms.txt

# Or start preview server and curl:
npx astro preview &
curl http://localhost:4321/llms.txt
curl http://localhost:4321/llms-full.txt
```

After deploying, paste your live URL into the [validator](/validator/)
to confirm spec compliance: exactly one H1, valid link syntax (`- [title](https://...)`), all URLs absolute, no empty sections.

## Which approach to choose

- **Static `public/llms.txt`**, best for sites updated infrequently.
Zero overhead, no TypeScript required, works everywhere. 
- **TypeScript endpoint `src/pages/llms.txt.ts`**, best for
documentation sites with many auto-generated pages. The file stays in sync automatically on
every build without manual edits.   
&rarr; [Full creation guide](/how-to-create/) &middot;
[Next.js guide](/llms-txt-nextjs/) &middot;
[WordPress guide](/llms-txt-wordpress/)

## Sources

- [ llmstxt.org, official spec ](https://llmstxt.org/)
- [ Astro, Content Collections ](https://docs.astro.build/en/guides/content-collections/)
- [ Astro, Endpoints ](https://docs.astro.build/en/guides/endpoints/)           
On this page

- [ Approach 1, Static file in public/ ](#approach-1)
- [ Approach 2, TypeScript endpoint with getCollection() ](#approach-2)
- [ Adding llms-full.txt ](#llms-full)
- [ Verify after build ](#verify)
- [ Which approach to choose ](#which)
