How to Add llms.txt to an Astro Site
Astro has no llms.txt file convention — and it is one of the few frameworks that
genuinely does not need one. Between the public/ directory and
src/pages endpoints, there are three clean ways to ship a spec-compliant
llms.txt, from a 30-second static file to a fully generated index.
Why Astro and llms.txt Are a Natural Fit
The llms.txt convention exists so AI engines and coding agents can find the handful of pages that matter on your site. Astro sites are usually built from Markdown and frontmatter — exactly the structured content llms.txt wants to point at. On top of that, Astro's default output is static: whatever the build produces is what your CDN serves, which makes a root-level text file trivial.
Two Astro behaviors do all the work. First, every file in
public/ is copied verbatim into the output root, so
public/llms.txt becomes /llms.txt automatically. Second,
any .ts file in src/pages/ becomes a route, so
src/pages/llms.txt.ts serves plain text at the same path. This very
site — llmstxtgenerator.dev — is an Astro 5 site and serves its own
llms.txt from the
public/ directory.
Method 1: Static File in public/ (30 Seconds)
Create public/llms.txt with your H1, a blockquote summary, and curated
sections of markdown links. This follows the
llmstxt.org v2 spec:
# Example Docs
> Example Docs is the official documentation for the Example platform.
> It covers installation, configuration, the API and troubleshooting.
## Getting Started
- [Quickstart](https://example.com/docs/quickstart): first project in 5 minutes
- [Installation](https://example.com/docs/install): system requirements and setup
- [Authentication](https://example.com/docs/auth): API keys and access tokens
## API Reference
- [REST API](https://example.com/docs/api): every endpoint, parameter and error
- [Webhooks](https://example.com/docs/webhooks): events your server can subscribe to
Run npm run build and check the output — the file appears at
dist/llms.txt, ready for any static host. Deploying to Cloudflare Pages,
Netlify or GitHub Pages requires no server config at all. Keep this method when your
important links rarely change; move to Method 2 when they do.
Method 2: Generate It at Build Time from a .ts Endpoint
For a file that should stay in sync with your site, create
src/pages/llms.txt.ts. Astro maps the filename to the
/llms.txt route, and on a static site the endpoint runs during the
build — the result is a real file on your CDN, with nothing executed at request time:
// src/pages/llms.txt.ts
import type { APIRoute } from 'astro';
const pages = [
['Quickstart', 'https://example.com/docs/quickstart', 'first project in 5 minutes'],
['Authentication', 'https://example.com/docs/auth', 'API keys and access tokens'],
['REST API', 'https://example.com/docs/api', 'every endpoint, parameter and error'],
];
export const GET: APIRoute = () {
const lines = [
'# Example Docs',
'',
'> Example Docs is the official documentation for the Example platform.',
'',
'## Documentation',
'',
];
for (const [name, url, summary] of pages) {
lines.push('- ' + name + ': ' + summary + ' (' + url + ')');
}
return new Response(lines.join('\n') + '\n', {
headers: { 'Content-Type': 'text/plain; charset=utf-8' },
});
};
Two details matter. The Content-Type must be text/plain —
agents and validators expect plain text, not HTML. And if you later add an adapter
for server-side rendering, add export const prerender = true to keep
generating the file at build time instead of on every request.
To go further, pull from your content collections instead of a hard-coded array.
Import getCollection from astro:content, map each post's
frontmatter title, description and URL into a markdown link line, and join them.
Your llms.txt then updates itself every time you publish content.
Method 3: The astro-slop Integration (Maintenance-Free)
If you run a large docs or blog site, the community
astro-slop
integration automates the whole pipeline. It generates an llms.txt
index from your pages, per-page Markdown versions of every route, a companion
llms-full.txt, and adds content negotiation plus
rel="alternate" link headers. It is the closest thing to a
"just works" llms.txt setup for Astro today — worth a look before you hand-roll
Method 2 on a big site.
Astro-Specific Checklist
- One source of truth — a
public/llms.txtfile and asrc/pages/llms.txt.tsroute that both target /llms.txt will drift apart. Pick one. - Absolute URLs only —
https://example.com/docs/start, never/docs/start. Agents resolve links from the file's location. - Serve text/plain — endpoints must set
Content-Type: text/plain; a validators may reject HTML responses. - Curate, don't dump — 10–50 links to canonical docs pages beat 500 links to marketing pages. See the format guide for structure rules.
- Add llms-full.txt for deep docs — if your reference section is large, link a generated llms-full.txt companion file.
- Keep it fresh — rebuild and redeploy whenever a listed page changes; stale files erode agent trust. The best practices guide covers maintenance cadence.
Verify and Deploy
After deploying, confirm the route serves plain text with a 200 status:
curl -s -o /dev/null -w "%{http_code} %{content_type}\n" https://your-domain.com/llms.txt
# Expect: 200 text/plain If you host on Cloudflare Pages, our Cloudflare Pages deployment guide covers the build configuration. Then paste your URL into the free llms.txt checker to validate the H1, the blockquote summary, absolute URLs and section structure before AI engines start reading it.
Build the initial curated file in seconds by running your sitemap through the
free llms.txt generator,
then validate the result with the
checker before deploying.
A correct, current llms.txt is one of the highest-leverage AI
visibility changes most Astro sites can make this week.