AGENTS.md on the site
Instructions for AI agents
One instruction for an agent that has received a link to the HERON repository and a task about a site. You do not need to read the HERON code: everything a site can and cannot do is written in the documentation. If the documentation and the behaviour of HERON disagree, that is a bug in HERON: put it in your report, do not work around it.
Below are the roles the work on a site is split into, the rules shared by every role and a map of the documentation. Each role has its own page with the details.
In plain words
An AI agent is a very fast assistant that does exactly what the instructions say and guesses when they say nothing. This page is the instruction. It splits the work on a site into four jobs — planning, writing, design, building — and for each job says what to read, what to produce and what never to touch.
Why it matters for you. Give an agent the link to this page (or heron docs --export), name the role, and it stops guessing: a writing agent fills pages and never edits the theme, a design agent changes only the theme, and every job ends with the same check — the strict build.
Example task for an agent: «Read AGENTS.md. Work in the content role. Add a page about roof repair by copying content/en/services/gutter.md, fill title, h1 and description, and run the strict build.»
You need this page when you hand work to an agent or to a person. Ready tasks to copy are on HERON for AI.
Documentation inside the image
No clone of the repository? The same documentation is inside the image, in exactly the version of HERON you run:
docker run --rm ghcr.io/fmstm/heron:prod docs # table of contents
docker run --rm ghcr.io/fmstm/heron:prod docs architect # one whole topic
docker run --rm ghcr.io/fmstm/heron:prod docs --search "E023" # search: file, line, context
docker run --rm -v "$PWD":/site -w /site --user $(id -u):$(id -g) \
ghcr.io/fmstm/heron:prod docs --export .heron-docs # as a folder, links work
Links in the documentation are paths in the repository; they are the same in the --export folder. Every command for reading the docs is on the page Docs in the terminal.
What HERON is, in a minute
HERON is a static site builder: the image ghcr.io/fmstm/heron:TAG (or a pip package with the heron command). It creates a site folder (new, init, page) and builds it by the contract (build, check, serve).
A site is a folder without any HERON code: site.yaml (the only settings file), content/en/ and a folder per other language (pages in markdown), media/, data/, static/, theme/. A page is a file, the file path is the address. Every file starts with an SEO block of eight groups, then an intro and sections ## Title {#anchor}. The theme puts the sections in place by their anchors.
If you see HERON for the first time, read Concepts: seven ideas everything else stands on.
H="docker run --rm -v $PWD:/site -w /site --user $(id -u):$(id -g) ghcr.io/fmstm/heron:prod"
$H new my-site --notes en --name "Site" --domain example.com --lang en,ru -y # no questions asked
$H check my-site # report without a build
$H build my-site --env prod --strict
Roles
The work on a site is split into four roles. One agent can go through all of them in a row, or get only one: then it works inside that role and hands the result on.
Architect ──▶ structure, site.yaml, types ──┬──▶ Designer ──▶ theme ──────────┐
└──▶ Content and SEO ──▶ pages ────┴──▶ Builder ──▶ site, image, report
| Task you receive | Role | Details |
|---|---|---|
| "Here is the old site or a report on it: design a new one" | Architect | Role: Architect |
| "Write the pages", "move the texts", "fix the SEO", "add a translation" | Content and SEO | Role: Content and SEO |
| "Make a theme", "build it from the mockup", "add a page type" | Designer | Role: Designer |
| "Build the site from the structure", "publish it", "pack it into an image" | Builder (and the other roles along the way) | Role: Builder |
Before you suggest a change to HERON, check What HERON can already do: almost everything a site needs is already there.
Architect
Goal. A site structure the other roles can work from without new questions.
Input. A report on the old site, an export, a sitemap, Search Console; or the client's description of the task.
Output.
- a "site structure" document following templates/structure.md: the page tree, keys, types, sections per type, languages;
- a draft
site.yaml(sample) and thetypes/linksparts oftheme.yaml(sample); - a move table: old address → key → new address per language → 301 or 410;
- questions for the client, each with options and a recommendation.
Read. What HERON can already do, the guides Concepts and SEO and moving a site, the contract: site folder, addresses and languages, site.yaml, theme.yaml.
Rules. The structure is built from what HERON can do, not from how the old site was put together. A type earns its place by its own layout. A page that belongs to several sections stays flat and is connected by links. A task for HERON only when the need is missing from the capabilities list.
Done when: every page has a key, a type and a language; every type has a list of sections with their forms; every old address has a 301 or 410 decision; every decision points to a part of the documentation.
Content and SEO
Goal. Pages that build without errors and an SEO block filled in with meaning.
Input. The structure from the architect (or an existing site), texts and facts from the client.
Output. Files content/en/…md (and other languages), images in media/, data in data/, redirect_from in the pages, a list of content debts and questions.
Read. The guides Pages and content and SEO; the sample page templates/page.md; the contract: page format.
Rules. A new page comes from heron page with a type and a name, or as a copy of a ready file; the SEO block is never shortened and its comments are never removed. title ≠ h1. Links to your own pages use the key from the root, without a language prefix. No material, no section. Contacts and company details go to site.yaml, not into the text.
Done when: check has no errors; every page has title, h1 and description; every image has alt; the "Not filled in" summary is copied into the report.
Designer
Goal. A theme that draws every page type from the structure and does not break on incomplete content.
Input. Types and sections from the architect, a mockup or a description of the look.
Output. theme/: theme.yaml, a template per type, a module per form, an i18n file per language, styles.
Read. The guide Theme and design; the contract: section forms, theme.yaml, images; the build: what a template sees.
Rules. A template holds no content texts and no site data: texts live in sections, company details in site.*, interface strings in t.*. Sections are drawn with mod.MODULE('ANCHOR'), with no conditions around them. Images only through picture().
Done when: every type in types has a template; every form in uses has a module; the build passes on the starter content and on the full content; the report lists no missing i18n strings.
Builder
Goal. A site that builds with --env prod --strict and answers with the right codes.
Input. The structure, site.yaml, the theme and the content, or a task "build it from the structure": then the builder runs the other roles too.
Output. A working site folder; dist/ or an image; a report: what was done, content debts, questions, warnings left and why.
Read. The guides Your first site and Build and deploy; error codes in the build specification, part 11.
Rules. site.yaml is the single source of truth: commands have no "language" or "theme" flags. No Dockerfile, compose file or .env goes into the site folder. A warning is either a content debt or a bug, never noise.
Done when: build --env prod --strict passes; smoke prod is green; the report is handed in.
Rules for every role
- Facts are never invented. Phone numbers, addresses, prices, deadlines, names, numbers and figures come only from the client's source. No fact, the field stays empty and the question goes on the list. HERON does not draw an empty block; it does draw an invented one.
site.yamlis the single source of truth about the site: languages, theme, domain, menu, counters, 410.- The site folder holds content only. Building and packing are done with HERON commands and
scripts/site.sh. - The page key is the file path, the address is the
slug. File names are the same in every language; links and the menu use keys. - Structure matters more than markup. The order of sections in a file does not matter; the markup of a section sets its form.
- A warning is work.
--strictturns warnings into errors, and that is how production is built. - HERON is not changed from inside a site. A missing capability is a task for HERON (template on the Architect page); on the site, use the simplest honest option.
Documentation map
| You need | Where |
|---|---|
| Concepts, first site, content, theme, SEO, deploy | the guides in order: Concepts, Your first site, Pages and content, Theme and design, SEO, Build and deploy |
File path → address, key, slug; links; old addresses; 404 |
Site folder and addresses (contract, §2) |
| Languages | Site folder and addresses (contract, §3) |
| SEO block, every page field | Page format (contract, §4.1–4.2) |
| Sections and their forms | Page format (contract, §4.3–4.4) |
Every site.yaml key |
site.yaml (contract, §5) |
theme.yaml: types, links, images |
theme.yaml (contract, §6) |
| Images, video, files | Images and files (contract, §7) |
| What a template sees | Build (§6–7) |
| Commands and flags | Build (§10) |
| Error codes | Build (§11) |
| Site image, nginx, smoke check | Distribution (§5) |
Samples are in the folder docs/agents/templates: structure.md, site.yaml, theme.yaml, page.md. HERON's tests check all of them: an outdated sample breaks the tests before you ever pick it up.
If you change HERON itself
This instruction is about sites; the HERON repository is separate work. There: uv sync --group dev, then ./scripts/check.sh before every commit. No site names, domains, slugs or subject words in code, tests or documentation: scripts/check-boundaries.sh checks this. Documentation changes in the same commit as the behaviour.
Source
This page mirrors AGENTS.md from the prod branch. The repository is updated first, so the newest version is always there: AGENTS.md on GitHub. The original is written in Russian.