HERON

Role for AI agents

Role: Designer

Make a theme that draws every page type from the structure and does not break on incomplete content. Shared rules are on the page Instructions for AI agents.

How a theme works, in plain words, is in the guide Theme and design.

In plain words

The designer makes the clothes of the site: the theme. It works only in the theme/ folder and never writes texts of pages there. A good theme looks right with a full page and with a half-empty one, because a missing block should simply not appear.

Example. The structure says pages of type «service» have the sections intro, prices and faq. The designer makes a template for «service», makes sure a table module draws prices and an accordion draws faq, and checks a service page without prices: the page still looks finished.

You need this page when you hand the design to an agent such as Claude Design or to a person. To see every block form the theme must draw, open the forms reference.

Input and output

Input: page types and their sections from the architect (or an existing theme.yaml), a mockup or a description of the look.

Output: the theme/ folder: theme.yaml, base.html, type templates, form modules, partials/, assets/, interface string files in i18n/ for every language.

1. Start from the starter theme

heron new writes a working theme: the types home, page, 404 and the modules breadcrumbs, cards, facts, faq, list, prose, steps. It builds from the first minute: change it step by step and build after each step.

2. theme.yaml

Sample: templates/theme.yaml; every key: the contract, theme.yaml.

types:
  home:     {uses: [intro, "why:list", "how:steps", "faq:faq"], jsonld: [WebSite]}
  category: {uses: [intro]}
  service:  {uses: [intro, "includes:list", "how:steps", "faq:faq"], jsonld: [Service]}
  article:  {uses: [intro, "*"], jsonld: [Article]}
  page:     {uses: [intro, "*"]}
  "404":    {uses: [intro]}
links:
  - {field: related, type: service, back: related_from}
images:
  ratios: ["1:1", "16:9"]
  • uses: all sections of the type, optional ones included; after the colon, the expected form (forms table). "*" means any sections. From uses, heron page writes placeholders and the report names empty sections;
  • jsonld: the structured data types for pages of this type;
  • requires: paths in site.yaml the theme cannot work without (E011 if empty);
  • links: link fields; back builds the reverse list.

3. Type templates

One template per type, templates/TYPE.html (otherwise E008):

{% extends "base.html" %}
{% block content %}
  {{ mod.breadcrumbs() }}
  {# the heading: page.h1 inside an h1 tag #}
  {{ mod.list('includes') }}
  {{ mod.steps('how') }}
  {{ mod.faq('faq') }}
  {% for p in page.related.get('related', []) %}
    {# a link to p.url with the text p.h1 #}
  {% endfor %}
{% endblock %}
  • mod.MODULE('ANCHOR') draws the section, or nothing if it is missing: no conditions needed around it;
  • page_of('KEY') is a page by its key; data.FILE is reference data; site.* is site.yaml in the page's language; t.* are interface strings;
  • paths in extends/include/import start from the theme root: {% extends "templates/page.html" %}, not "page.html";
  • your own macros are imported in every template: an import in base.html is not visible to child templates. mod needs no import;
  • your own page fields: page.meta.get('topic'), no declaration needed; do not list them in fields (E023);
  • site.* is already in the page's language in every block: site.contact.address on a Russian page is address_ru, no need to pick the language by hand;
  • the full list of variables: build, §7; the page model: build, §6.

4. Modules

One module per form the theme draws: modules/NAME.html. Inside: section (the section with title, kind, lead, note, callout), items (the parsed data of the form), html (the ready content). What items holds for each form: the forms table (§4.4).

5. Images and assets

  • only picture(src, ratio, alt=…): sizes, WebP/AVIF, dimensions; building a picture tag by hand means losing the variants;
  • the ratios you use go into images.ratios;
  • CSS, JS, fonts in theme/assets/; favicon and .well-known in the site's static/.

6. Interface strings

Everything that belongs to the theme rather than the page ("Read more", "Questions and answers") goes into theme/i18n/en.yaml and the same file for other languages; in a template it is t.KEY. One file per site language; init writes a blank one. The keys on, off, yes, no go in quotes.

7. What a theme does not do

  • it holds no content texts and no site details: texts live in sections, phone and address in site.contact.*;
  • it does not load content with a script: text and numbers must be in the HTML;
  • it does not show the build stamp in production: {% if not env.is_prod %}{{ env.stamp }}{% endif %};
  • it outputs counters only when env.analytics is set.

Checklist

  • every type in the structure has an entry in types and a template
  • every form in uses has a module
  • the build passes on the starter content and on the full content
  • templates hold no texts or company details; interface strings go through t
  • the report lists no missing i18n strings and no template errors
  • images go through picture(); ratios are declared

Source

This page mirrors docs/agents/designer.md from the prod branch. The repository is updated first: designer.md on GitHub. The original is written in Russian.