How Heine builds a site
Heine builds a model of a site before it writes the site. That model gives pages, assets, translations, collections, and generated files stable identities such as page and asset IDs, plus checked relationships. Templates present those resolved facts. They do not create new pages, routes, or output files.
This guide explains that boundary. It is an overview of Heine's current architecture, not a replacement for the reference or a guide to its Rust modules.
The build pipeline
Each full build follows one direction:
authored inputs
-> discovery and source checks
-> resolved Site model and output claims
-> Markdown analysis and derived page facts
-> template rendering
-> staged output
-> atomic publicationHeine first discovers the inputs below the site root, assigns them their roles, and rejects unsafe paths and symbolic links. It then resolves the relationships that need knowledge of the complete site.
That step creates the stable Site model and a checked plan for every output Heine owns. An output claim records that one page, copied asset, deployment file, or generated resource owns one output path. A collision or a missing relationship fails at its authored location before Heine publishes a partial site.
Markdown analysis then derives page facts such as heading anchors, word counts, reading-time estimates, and search text. It also resolves checked Markdown links and assets. Templates render only after that analysis. They receive deliberate views of the resolved model, such as a page, an asset, a collection, or a taxonomy. They can choose how to present those views, but they cannot invent output ownership or change the relationships that Heine has already resolved.
Finally, a full build writes the complete managed output to a staging tree. It publishes that tree only after every render succeeds, so a failed build leaves the previous published output intact.
What a full build guarantees
A successful full build has resolved the relationships Heine owns, rejected output collisions, rendered every planned page and generated resource, and published a complete replacement of its managed output tree.
That guarantee has deliberate limits. Heine does not verify external URLs,
literal URLs or manually chosen IDs in trusted raw HTML, references in CSS or
JavaScript, or the #fragment suffix after a checked page: link. It checks
the page part of page:guide/install#section, then preserves #section for
the browser.
What belongs to each domain
Heine keeps the main authored roles separate because they have different validation and output behavior:
- Content holds pages, declared Markdown inputs, and copied assets. A page declaration chooses its inputs. Declared inputs are not copied.
- Configuration, locale trees, and the selected kit establish site-wide behavior, localized identity, and the available presentation boundary.
- Data supplies global structured values to templates. It is not published and does not provide arbitrary filesystem access.
- Templates and Fluent messages describe presentation. Templates receive resolved views, and messages hold reader-facing text.
- Generated resources consume resolved facts. Listings, feeds, sitemaps, search documents, and renderer resources each have an explicit output claim.
- Output-attached files include deployment files and optional license declarations. They attach to the copied output inventory without becoming pages or template-controlled output.
This separation lets a template link to a known page without creating one, and lets Markdown refer to a checked asset without gaining unrestricted file access.
Checked relationships
Heine checks relationships that need knowledge of the complete site. These
include a page: Markdown link naming a rendered page, an asset: URL or
asset() call naming a copied asset, locale counterparts, collection
membership, and generated routes that must not collide with other output.
For example, when Markdown contains [Install](page:guide/install), Heine
resolves guide/install against the current locale's page catalog during
Markdown analysis. A missing page reports the link's authored source location.
A known page renders with its resolved URL.
Ordinary literal web URLs remain ordinary content. Heine does not pretend that it can verify arbitrary external URLs or rewrite all HTML, CSS, and JavaScript references. When an author needs a checked internal relationship, they use the corresponding typed Markdown form or template function.
Markdown, templates, and external tools
Markdown is prose by default. Tera2 runs in templates, where its inputs and
output role are explicit. This lets authors write literal {{ ... }} and
{% ... %} in Markdown, including code examples, without creating a second
templating phase or changing Markdown-derived facts after resolution.
Some Markdown constructs have a narrow structural contract. :::picture
connects one authored construct to checked assets, and :::render[...]
connects one request to a checked renderer result. They do not become a general
extension or plugin system.
External CSS and JavaScript bundling, media processing, remote fetching, deployment, and provider integration remain ordinary external tools. An external tool must produce its final asset before Heine reads it. Processing Heine-managed output afterwards can invalidate versioned URLs or integrity metadata.
Quick builds and the development server
heine --quick trades completeness for a faster edit cycle. It updates known
changed inputs in place, but it can retain stale output and cannot reliably
discover every relationship, configuration, template, rename, or deleted-input
change. Use a full build before deployment and whenever a change can affect the
wider site model.
The development server performs complete rebuilds before it publishes a new generation. It therefore gives local preview the same resolved-model behavior as a full build.
Where to continue
The tutorial shows how a site grows from a small page into a multilingual blog. The reference defines every current field, template value, function, and constraint. Focused guides explain each domain in detail.