How to Set Up llms.txt in Static Sites (Astro, Hugo, Eleventy)
Static-site generators (Astro, Hugo, Eleventy, Gatsby) make llms.txt clean: generate the file at build time from your content data, serve from /llms.txt root. This guide covers SSG-specific llms.txt. Pair with llms.txt guide and the WordPress version.
Step-by-step: How to set up llms.txt in static sites
- Pick content to include. Curated list of your most valuable content: top blog posts, comprehensive guides, About/FAQ. 20-100 entries. Not full sitemap (different file).
- Astro: create src/pages/llms.txt.ts. Astro supports custom endpoints. Create src/pages/llms.txt.ts that exports a GET function returning Response with text/plain content. Build collects all posts via getCollection() → builds markdown output.
- Hugo: create layouts/_default/llms.txt and content/llms.md. Hugo: content/llms.md with content. layouts/_default/llms.txt template loops over .Site.RegularPages → outputs markdown lines. Configure mediatypes in config.toml to add text/plain. Output goes to public/llms.txt at build.
- Eleventy: create llms.njk template. src/llms.njk: --- permalink: /llms.txt --- followed by Nunjucks template iterating collections.all → outputting markdown lines. Set permalink to ensure file generates at /llms.txt root.
- Gatsby: create gatsby-node.js custom file. gatsby-node.js → onPostBuild hook → use fs.writeFileSync to write public/llms.txt with content built from GraphQL queries.
- Validate file at /llms.txt. After build: visit yoursite.com/llms.txt. Should be text/plain (not text/html). Should contain markdown content. Test from curl: curl -I yoursite.com/llms.txt → Content-Type should be text/plain.
- Monitor. Periodically (monthly) review llms.txt output is current with site content. Static generation means file is rebuilt on every deploy — stale only if you forget to deploy.
🤖 Validate static llms.txt
Check your llms.txt is accessible and well-structured.
Run llms.txt Check →Frequently Asked Questions
Why static sites are best suited for llms.txt?
Build-time generation means llms.txt is data-driven and always current. Content additions auto-update. No CMS plugin needed. Free to host on Vercel/Netlify/Cloudflare Pages. Static-site llms.txt deployments are typically the cleanest of any platform.
How do I include only featured posts in llms.txt?
Filter at generation time. Astro: getCollection('blog').filter(p => p.data.featured). Hugo: .Site.RegularPages filter (where featured eq true). Eleventy: collections.featured tag in front matter. Gatsby: GraphQL filter in onPostBuild. Curate intentionally; don't dump everything.
Should llms.txt content be markdown or plain text?
Markdown — that's the format AI agents expect. Headers (##), links ([title](url)), descriptions. Structured for parsing while staying human-readable. Plain text without markdown loses structure.
Can I generate llms-full.txt too (with full content not just links)?
Yes. Same pattern with longer template that includes article body. Larger file (50-500KB typical), more useful for AI agents that consume it. Some agents look for llms-full.txt specifically; offering both is best.
How does Astro Content Collections help build llms.txt?
Content Collections (Astro 2.0+) provide typed access to content. getCollection('blog') returns all blog posts with type-safe frontmatter access. Filter, sort, format → output as markdown. Much cleaner than glob-and-read approaches.