How to Add llms.txt to Hugo
Hugo is a static site generator written in Go that ships as a single binary and
builds plain files into public/. It has no native
llms.txt feature — and it barely needs one. A file in
static/ becomes your site root file automatically, and a custom
output format can generate an llms.txt from your real content at
build time. Both routes are covered here.
Hugo and llms.txt: No Built-In Support (Yet)
As of 2026 there is no native llms.txt feature in Hugo and no Hugo entry on the
integrations list at llmstxt.org. The official Hugo forum hosts a thread titled
"Support for llms.txt standard for AI crawlers" that tracks community interest,
but the practical answer is that you do not need a plugin. Two long-standing Hugo
mechanisms do all the work: the static/ directory, which is copied
verbatim into the output root on every build, and custom output formats, which let
Hugo emit any file type next to your HTML.
Hugo's model also keeps the format honest: what public/ contains is
exactly what your CDN serves, with no server-side rendering in between. Hugo
powers a large share of documentation and blog sites on the web, and several
Hugo developers already publish the file this way — for example
Duncan Mackenzie's Hugo blog
serves /llms.txt plus a Markdown version of every post.
Method 1: static/llms.txt, the 60-Second Route
Create static/llms.txt in your project root. Hugo copies every file
in static/ to the root of public/ without touching it,
so on the next hugo build the file is live at
https://your-domain.com/llms.txt. Use the
llmstxt.org v2 spec
structure:
# Acme Docs
> Acme Docs is the official documentation for the Acme platform.
> It covers installation, configuration, the REST API and troubleshooting.
## Getting Started
- [Quickstart](https://acme.com/docs/quickstart): first project in five minutes
- [Authentication](https://acme.com/docs/auth): API keys and access tokens
- [Deployment](https://acme.com/docs/deploy): production setup for self-hosting
## API Reference
- [REST API](https://acme.com/docs/api): every endpoint, parameter and error
- [Webhooks](https://acme.com/docs/webhooks): events your server can subscribe to
Run hugo and check public/llms.txt appeared, then deploy
public/ to Netlify, Cloudflare Pages or any static host. Keep this
method when your curated list changes rarely; a hand-written file is the easiest
thing to audit and the easiest to forget. Remember absolute URLs — never relative
paths, which agents resolve inconsistently.
Method 2: Auto-Generate llms.txt at Build Time
When your content changes weekly, a generated file stays honest. Hugo's custom
output formats emit arbitrary file types. First, register a plain-text format in
hugo.toml whose baseName is llms:
[mediaTypes."text/plain"]
suffixes = ["txt"]
[outputFormats.llms]
mediaType = "text/plain"
baseName = "llms"
isPlainText = true
root = true
Next, create a content page that opts into the format. Hugo renders it through a
template named for the format's suffix (.txt), so add
layouts/_default/single.txt that outputs the page body with
.RawContent and then walks your site to append link lines:
# content/llms.md
+++
title = "Acme Docs"
outputs = ["llms"]
+++
# Acme Docs
> Acme Docs is the official documentation for the Acme platform.
> It covers installation, configuration, the REST API and troubleshooting. {{ .RawContent | safeHTML }}
## Pages
{{- range .Site.Pages -}}
- [{{ .Title }}]({{ .Permalink }})
{{- end -}}
Run hugo and the file is written to public/llms.txt.
Filter .Site.Pages in the template to include only the sections you
curate — dumping every tag and taxonomy page defeats the purpose of a curated
index. A minimal, ready-to-read reference implementation is the
roverbird/llms-hugo
repository on GitHub, and the same technique can emit Markdown versions of
individual pages for agents that want full text, the pairing the
llms.txt vs
llms-full.txt guide explains.
The Hugo-Specific Checklist
- One source of truth — a
static/llms.txtfile and a generatedcontent/llms.mdpage that both target /llms.txt will overwrite each other unpredictably. Pick one route. - Set baseURL before building — generated links use
.Permalink, which is built from yourbaseURL. A placeholder baseURL ships broken links into your llms.txt. Also avoidrelativeURLs = true, which produces relative paths agents resolve inconsistently. - Absolute URLs only —
https://acme.com/docs/quickstart, never/docs/quickstart. - Mind multilingual sites — a file in
static/is served for every language version. If each language needs its own file, give it its own directory via thestaticDiroption in the language block. - Curate, don't dump — list the 5–15 pages that answer real questions and skip marketing and tag pages. Curation rules live in the best practices guide.
- Rebuild to publish — Hugo has no server runtime. Every change to the file or your content requires a build and deploy, so wire llms.txt into your existing release pipeline.
Verify Before AI Engines Read It
After deploying, confirm the file 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
Hugo sites are usually deployed through CI, so check the build that is actually
live — a stale public/ folder is the most common reason a fresh
llms.txt goes missing. Then paste the URL into the free
llms.txt checker to
validate the H1, the blockquote summary, absolute URLs and the section structure.
Draft the initial file in seconds by feeding your Hugo sitemap into the
free llms.txt generator,
then verify the output with the
checker before wiring up
a template. Hugo makes the file easy to ship and easy to keep honest — a correct,
current llms.txt is one of the highest-leverage AI visibility changes
a static site can make this week.