AI-agent support
.md twin, the site root an llms.txt, and the reader a way to hand the current page to ChatGPT or Claude.An HTML page carries a sidebar, scripts and styles, and a model has to strip
that shell before reading it. OINK emits the same content a second time as plain
Markdown: one .md per page, one llms.txt index at the site root, and a “copy
as Markdown” button on the page. All three are build-time artifacts, with no
runtime service and no content negotiation.
All three have to be declared by the site under outputs; the theme does not
turn them on.
A .md per page
markdown is one of Hugo’s built-in output formats. Add it to the page kinds
that need it:
That is this site’s configuration. Each key under outputs is a wholesale
replacement rather than a merge: adding markdown means writing back every
format that kind already had (RSS, print), and omitting one loses that
output.
The URL rule is the page URL plus index.md:
| Page | Markdown |
|---|---|
/docs/customize/agents/ |
/docs/customize/agents/index.md |
/docs/customize/ (section index) |
/docs/customize/index.md |
/ (site home) |
/index.md |
Each HTML page’s <head> also carries a discovery link, so a crawler need not
guess the URL:
What the .md contains
It is not rendered HTML converted back to Markdown but the source you wrote: the front matter becomes an H1 and a blockquoted summary, and the body follows verbatim, with shortcodes expanded in place into their own Markdown forms.
Components in their native Markdown form (callouts, tables, field lists, image
attribute lines, code fences, data fences) keep their source in the .md, so
what the model reads is what you wrote. A section index additionally appends a
Section pages: list of child links after the body.
Shortcode forms each have a defined degradation: a
badge becomes emphasized text or a link, a
key becomes Ctrl + K,
tabs become a run of **Label** subsections, and
fields become an item list. Each component page’s
Output section states its own row.
Where the site has not enabled the LLMS output, that LLMS index: line does
not appear: the theme never points at a file it did not publish.
llms.txt
llms.txt is a plain-text manifest at the site root
telling a model what the site holds and where the machine-readable versions
are. Add the LLMS output format to the home page to generate it:
A multilingual site gets one per language: /llms.txt and
/zh/llms.txt. The content is a generated site index:
Where the three sections come from: Site index is this language’s home page
plus the site’s main menu (menus.main, linking the Markdown version where an
entry has one, and carrying description where present); Documentation index
is the docs section’s subsections and the level of pages beneath them, indented
by level, each row carrying that page’s description; Site locales is every
language in the site configuration. Menu entries pointing off-site (GitHub, an
issue tracker) are dropped: they belong to the navigation shell rather than to
this site’s content.
The way to improve llms.txt is through the main menu and each section index’s
description, not through this template.
Agent actions on the page
Four entries in the action menu at the right of the breadcrumb row relate to agents:
| Entry | What it does | When it appears |
|---|---|---|
| Copy as Markdown | Fetches this page’s .md into the clipboard (prefetched on hover, so a click has no perceptible wait) |
This page has a markdown output |
| View Markdown source | Opens the .md in a new tab |
This page has a markdown output |
| Open in ChatGPT | Jumps to ChatGPT with a prompt | assistant_links: true |
| Open in Claude | The same, to Claude | assistant_links: true |
The first two exist as soon as the markdown output is on. “Copy” is the left
half of the split button (the clipboard icon), and shows a brief tick on
success.
The last two are off by default and must be enabled explicitly:
Where the boundary lies once enabled: on a click, the runtime composes a prompt
using the full URL from the address bar (real domain, query string and anchor
included) — in English, “Please read the contents of
A page may narrow the site policy but not reverse it: front matter
page_context_menu: { assistant_links: false } turns the assistant links off
for that page, while writing true where the site has not enabled them has no
effect. To turn the whole menu off for a page, use page_context_menu: false —
see Page parameters.
Both assistant actions are also searchable in the command palette, from the same action manifest — see Command palette.
Opting a page out of .md output
Rewrite outputs in the page’s front matter. It is likewise a wholesale
replacement, so write only the formats you keep:
To keep RSS and drop only Markdown, list the rest:
Customizing the output
The theme renders Markdown output with layouts/all.md and generates
llms.txt with layouts/index.llms.txt. A site replaces either wholesale by
placing a file of the same name under its own layouts/, but consider a
narrower approach first:
- Per content type: a typed path such as
layouts/blog/single.mdorlayouts/docs/list.mdaffects only that kind of content, which is how the theme’s own print templates are specialized (layouts/blog/single.print.html). Check the template lookup order for your combination. - Per shortcode: a site’s own shortcode can have an output-format-specific template giving it a more machine-readable form in Markdown output.
- Per page: hand-writing the content of a few high-value pages costs less than changing a template.
The content of llms.txt follows the site’s structure, so before changing the
template, confirm the problem is not in the main menu or a description.
Verify
With curl, against production or a local preview:
Then check three things:
- Any page’s HTML
<head>hasrel="alternate" type="text/markdown"; - Clicking the copy button at the right of the breadcrumb row and pasting yields Markdown rather than HTML;
llms.txtcontains no off-site links.
Limits
- The machine-readable surface the theme produces is exactly two things: a
.mdper page andllms.txt. There is nonav.jsonand no other structured index interface; the sitemap is still Hugo’s ownsitemap.xml. - The
LLMSoutput format is declared as a non-alternative format, sollms.txtnever appears in the<head>alternate links and has no page action. It is discovered by its conventional root path. - Server-side content negotiation (one URL returning Markdown for
Accept: text/markdown) is outside the theme’s scope and belongs to the hosting layer. - Markdown output follows the source path: content generated only in the browser by JavaScript (a runtime-drawn chart) appears in the
.mdas fence source, not as a diagram.
Related
- Print — the other non-HTML output
- Command palette — the other entry point to the assistant actions
- Page parameters —
outputs/assistant_links/page_context_menu - Navigation and menus —
llms.txt’s site index comes from the main menu - Configuration — full definitions of
outputsandparams.ui.page_context_menu.*