Heine reference

This is the complete current contract for Heine-authored files, command options, and template values. Start with the README or tutorial when building a site for the first time; use this page to look up exact fields, defaults, constraints, functions, and filters. The glossary defines Heine-specific vocabulary used below.

heine.toml, .page, and _directory.toml use strict schemas: unknown fields are rejected. TOML loaded from data/ or declared as page content is arbitrary structured data.

Site root and commands

A site root contains heine.toml, content/, and templates/; data/, deploy/, LICENSES/, and locales/ are optional. Without --root, Heine checks the current directory and each parent directory. It never searches child directories.

CommandOptionDefaultAllowed valuesEffect
heine--root <path>nearest ancestor site rootexisting site rootSelects the site root
heine--quickoffflagUpdates managed output for changed page, declared content, inherited descriptor, data, Fluent resources, present copied assets and sidecars, deployment files, and license texts; it remains incomplete
heine--clean-outputoffflagAdopts unmanaged output; conflicts with --quick
heine serve--root <path>nearest ancestor site rootexisting site rootSelects the site root
heine serve--clean-outputoffflagAdopts unmanaged output before its initial build
heine serve--draftsoffflagIncludes otherwise unpublished draft = true pages in this local preview
heine serve--host <address>127.0.0.1IP addressInterface on which to listen
heine serve--port <number>11111024-65535First port to try; then the next free port

--quick does not apply to serve.

heine.toml

heine.toml is required. Its [i18n] section is required; other sections and fields use the following defaults.

FieldTypeDefaultAllowed values and constraintsEffect
site.base_pathstring"/"ASCII absolute URL directory path; starts and ends with /; uppercase percent escapes only; no encoded separators or dot segmentsPrefix for Heine-generated absolute URLs, including asset(), page(), and taxonomy links
site.originstringabsentAbsolute http or https origin only: host and optional port, without credentials, query, fragment, or deployment pathRequired by sitemaps and Atom feeds for canonical URLs
site.time_zonestringabsentIANA time-zone name such as "Europe/Berlin"; resolved from Heine's bundled databaseResolves authored published and updated local times deterministically
build.output_dirstring"public"Non-empty relative path with portable filename components; cannot be content/, data/, deploy/, LICENSES/, templates/, locales/, or a descendantGenerated output directory relative to site root
assets.integritystringabsent"sha256", "sha384", "sha512"Enables Subresource Integrity values from asset()
licensing.requiredbooleanabsenttrue only; false is a checked errorRequires one licensing declaration for every copied asset
licensing.groupsarray of tables[]Exact non-empty copied-asset output_path list and sidecar-style SPDX fields; no overlap, sidecar conflict, glob, or unknown fieldsApplies one shared declaration to a coherent asset set
i18n.default_localestringrequiredCanonical BCP-47 locale declared by an i18n.locales.<code> tableLocale with unprefixed generated URLs
i18n.localestablerequiredNon-empty table keyed by canonical BCP-47 locale codesFinite locale source trees to render
i18n.locales.<code>.directionstringrequired"ltr" or "rtl"Base HTML writing direction for that locale
collections.<name>.orderstringrequired"published-asc", "published-desc", "title-asc", "title-desc", "weight-asc", "weight-desc", "id-asc", or "id-desc"; <name> is a simple identifierDefines a named, locale-local ordered set of rendered pages
series.pathstringrequired when enabledPortable relative output path outside __heine/Locale-relative generated Series root
series.index_templatestringrequired when enabledLogical template name below templates/Renders every locale's Series index
series.listing_templatestringrequired when enabledLogical template name below templates/Renders non-empty Series listings and their pagers
series.index_title_keystringrequired when enabledNon-empty Fluent message identifierLocalized generated-index title
series.index_description_keystringabsentNon-empty Fluent message identifierOptional localized generated-index description
series.per_pageintegerrequired when enabledPositive integerMembers on every generated Series listing page
series.definitionstablerequired when enabled; may be emptyKeys are literal portable URL components without percent escapesDeclares the Series catalogue
series.definitions.<id>.title_keystringrequiredNon-empty Fluent message identifier; <id> is a literal portable URL component without percent escapesLocalized Series title and listing route component
series.definitions.<id>.description_keystringabsentNon-empty Fluent message identifierOptional localized Series description
search.<name>.collectionsarray of stringsrequiredNon-empty array of distinct configured collection names; <name> is a simple identifierSelects and unions locale-local members for one JSON search index
search.<name>.pathstringrequiredPortable relative output path ending in lowercase .json, outside __heine/Locale-relative logical JSON output path
search.<name>.versionedbooleantruetrue or falseInserts a full JSON SHA-256 digest before .json, or retains the stable configured path
feeds.<name>.collectionstringrequiredConfigured collection name; <name> is a simple identifierSelects the locale-local members that supply Atom entries
feeds.<name>.pathstringrequiredPortable relative output path outside __heine/Locale-relative Atom output path
feeds.<name>.title_keystringrequiredNon-empty Fluent message identifierLocale-local Atom feed title
feeds.<name>.subtitle_keystringabsentNon-empty Fluent message identifierOptional locale-local Atom feed subtitle
feeds.<name>.limitinteger20Positive integerMaximum chronological entries in each locale feed
feeds.<name>.empty_updatedTOML local date-timeconditionally requiredSame form as published; required when a locale feed is emptyAtom update time for an empty locale feed
feeds.<name>.empty_authorsarray of stringsconditionally requiredNon-empty author names; required when a locale feed is emptyAtom authors for an empty locale feed
taxonomies.<name>.collectionstringrequiredConfigured collection name; <name> is a simple identifierSelects and orders the taxonomy's rendered members
taxonomies.<name>.pathstringrequiredPortable relative output path outside __heine/Generated taxonomy root
taxonomies.<name>.index_templatestringrequiredLogical template name below templates/Renders the taxonomy's term index
taxonomies.<name>.term_templatestringrequiredLogical template name below templates/Renders each term listing and its pagers
taxonomies.<name>.per_pageintegerrequiredPositive integerMembers on each generated term-listing page
taxonomies.<name>.counterparts.<group>.<locale>stringabsentAn existing literal term for a configured locale; each non-empty opaque <group> has at least two locale members, and a locale-term pair occurs in at most one groupDeclares a deliberate cross-locale term counterpart
sitemaptableabsentEmpty table; requires site.originGenerates canonical sitemap output
markdown.extensionsarray of strings[]Unique subset of "tables", "strikethrough", "task_lists", "footnotes"Enables Markdown extensions
markdown.mathstring"off""off", "mathml", "tex"Selects ordinary Markdown, build-time MathML, or escaped TeX passthrough
markdown.margin_footnotes.marker_messagestringabsentNon-empty Fluent message identifier; Heine supplies $number when formatting it; requires at least one effective page or directory footnote settingLocalized accessible name for margin-footnote controls
markdown.highlighting.stylesheetstringabsentSafe site-output-relative path ending in .css; cannot use __heine/Generated class-based syntax stylesheet
markdown.highlighting.missing_languagestring"error""error", "plain"Unknown fenced-language policy
markdown.highlighting.theme.lightstringrequired when highlighting is enabledBundled Giallo theme name; see the linked list belowLight syntax palette
markdown.highlighting.theme.darkstringrequired when highlighting is enabledBundled Giallo theme name; see the linked list belowDark syntax palette

Collection definitions establish relationships only; they do not write output. Every configured collection exists in every locale, including when it is empty. Page IDs are the final deterministic tie-breaker. Published orders require every member to declare published; title orders use the collection locale's ICU collation and require titles, and weight orders require numeric weights on every member.

Taxonomies turn one configured collection into locale-local generated index and term-listing pages. Their terms are literal display and route components; they are neither slugified nor inferred across locales. See taxonomies for the route and rendering model.

Atom feeds turn one configured collection into one XML document per locale. They use collection membership but order entries by published descending, then page ID. See Atom feeds for entry requirements, empty locale feeds, and template discovery links.

Search indexes turn one or more configured collections into one JSON document per locale. Their union is ordered by page ID, independently of every collection's display order. The complete document is content-hashed by default; --quick does not update it. See search indexes for the JSON and browser-boundary contract.

The complete set of accepted theme names is in Giallo's source README under “Themes”; the linked source matches Heine's bundled registry. Use those exact names; Heine reports an unknown name at its configuration location.

Search indexes

Each configured index writes one UTF-8 JSON document per configured locale:

{
  "format": 3,
  "locale": "en",
  "documents": [
    {
      "id": "blog/example/index",
      "url": "/guide/blog/example/index.html",
      "draft": false,
      "title": "Example",
      "description": null,
      "summary": "A short example.",
      "published": "2026-08-14T07:30:00Z",
      "updated": null,
      "taxonomies": { "tags": ["Rust"] },
      "sections": [
        { "fragment": null, "text": "Source-derived opening text." },
        { "fragment": "installation", "text": "Installation\n\nSource-derived section text." }
      ]
    }
  ]
}

format is the positive schema version, currently 3. id is the locale-relative page ID and url names the literal generated page file with site.base_path applied. draft is true only in a heine serve --drafts index. title, description, summary, published, and updated are their authored page facts or null. taxonomies has configured taxonomy names in deterministic lexical order, with literal locale-local terms in authored order. Documents are ordered by page ID.

sections preserves every declared .md input in content-name order as non-empty source-derived text sections. Each section has text and a fragment. fragment is null unless the section begins at a Markdown heading with a generated identifier from the page's effective table of contents. A browser can search section text and append a non-null fragment to the document URL, or search all sections as one document by joining their texts. The source text includes headings, link labels, image alternatives, code, and recognized math source. Source-authored raw HTML adds text nodes and img alt values, while markup, comments, URLs, attributes, and script, style, or template contents do not contribute. Soft and hard Markdown breaks remain line feeds; block boundaries become two line feeds. Heine does not lower-case, tokenize, stem, truncate, or derive text from rendered HTML.

_directory.toml

Place _directory.toml in a configured content/<locale>/ tree. It is non-rendered, non-published, and provides directory metadata plus recursive policy.

title = "Blog"

[metadata]
required = ["title"]

[pages]
template = "post.tera"

[pages.metadata]
required = ["title", "published", "extra.author"]
FieldTypeDefaultAllowed values and constraintsEffect
titlestringabsentTOML stringpage.directory.title
descriptionstringabsentTOML stringpage.directory.description
summarystringabsentTOML stringpage.directory.summary
extraTOML tableempty tableDot-addressable keys; rules belowpage.directory.extra
metadata.requiredarray of strings[]title, description, summary, or extra.<name>Adds requirements for this and nested descriptors
pages.templatestring or booleanabsentTemplate below templates/, or falseRecursive default; closest descriptor wins
pages.collectionsarray of stringsinheritedUnique configured collection names; an empty array opts outRecursive default membership for descendant pages
pages.authorsarray of stringsinheritedNon-empty author namesRecursive author default; a page list replaces the nearest one
pages.sitemapbooleanabsentOnly false, and only when global [sitemap] is enabledRecursively excludes descendant rendered pages and their pagers; no descendant may re-include them
pages.toc.contentstringabsentSimple declared-content name for one unsegmented .md file; each effective descendant renders it exactly once with markdown(content="…")Recursive default table-of-contents source
pages.toc.min_levelinteger1Integer from 1 through 6Lowest heading level exposed through the table of contents
pages.toc.max_levelinteger6Integer from 1 through 6; not lower than min_levelHighest heading level exposed through the table of contents
pages.tocbooleanabsentOnly false; requires an otherwise effective inherited table of contentsSuppresses that inherited default for this descriptor subtree
pages.footnotes.contentstringabsentSimple declared-content name for one unsegmented .md file; each effective descendant must renderRecursive default margin-footnote source
pages.footnotesbooleanabsentOnly false; requires an otherwise effective inherited margin-footnote settingSuppresses that inherited default for this descriptor subtree
pages.metadata.requiredarray of strings[]title, description, summary, authors, published, updated, or extra.<name>Adds requirements for descendant pages

Requirements accumulate from content/<locale>/_directory.toml to a page or nested descriptor. A page template overrides its inherited default; template = false explicitly disables rendering.

*.page

Each .page defines a page. Its ID is its path below its content/<locale>/ tree without .page. Without a template, it has no output path and cannot be resolved with page().

FieldTypeDefaultAllowed values and constraintsTemplate field / effect
templatestring or booleaninherited, or absentTemplate below templates/, or falseDetermines output; false disables inherited rendering
draftbooleanabsentOnly true; omit for ordinary publication; never inheritedExcludes this page from ordinary builds and exposes page.draft in previews
titlestringabsentTOML stringpage.title
descriptionstringabsentTOML stringpage.description
summarystringabsentAuthored TOML string; never derived from Markdownpage.summary
authorsarray of stringsinherited, or absentNon-empty author namespage.authors; required for Atom feed entries
publishedTOML local date-timeabsent2026-08-14T09:30:00; requires site.time_zonepage.published as UTC RFC 3339 text
updatedTOML local date-timeabsentSame form as published; must not be earlier than itpage.updated as UTC RFC 3339 text
sitemapbooleanabsentOnly false, and only when [sitemap] is enabledExcludes this rendered page and its derived pagers from the sitemap
toc.contentstringabsentRendered page; simple declared-content name for one unsegmented .md file, rendered exactly once with markdown(content="…")Selects the page's table-of-contents source
toc.min_levelinteger1Integer from 1 through 6Lowest heading level exposed through page.toc
toc.max_levelinteger6Integer from 1 through 6; not lower than min_levelHighest heading level exposed through page.toc
tocbooleanabsentOnly false; requires an otherwise effective inherited table of contentsSuppresses that inherited directory default for this page
footnotes.contentstringabsentRendered page; simple declared-content name for one unsegmented .md file; requires the footnotes extension and global marker messageSelects the page's margin-footnote source
footnotesbooleanabsentOnly false; requires an otherwise effective inherited margin-footnote settingSuppresses that inherited directory default for this page
taxonomies.<name>non-empty array of stringsabsent<name> must be configured, the page must belong to its source collection, and terms are literal portable filename componentspage.taxonomies.<name> term links
weightinteger or boolean0, except index pagesInteger, or exactly false on a non-index pagepage.weight; false excludes a non-index page from sibling ordering
suffixstring".html"Non-empty extension without /, \, NUL, ., or ..Rendered filename extension
translationidstringabsentNon-empty opaque identifier; at most once per localeExplicitly joins pages across locales as page.translations
collectionsarray of stringsinherited, or []Unique configured collection names; only rendered pages may belongReplaces the inherited membership default; [] opts out
seriesarray of tables[]Each table has configured id and positive position; membership is not inherited; only rendered titled pages may belongAdds this page to one or more ordered locale-local Series
pagination.collectionstringabsentConfigured collection name; page must renderMakes this authored page a collection listing
pagination.per_pageintegerrequired when paginatingPositive integerCollection members on each pager
pagination.segmentstring"page"Literal ASCII letters/digits or -._~!$&'()*+,;=@; no percent escapes, ./.., or trailing .Generated-pager route segment
pagination.navigation.windowinteger1Integer from 1 through 5Compact navigation link radius around boundaries and current pager
content.<name>stringabsent<name> is a simple template identifier; path is relative to page and remains under its locale treepage.content.<name>; input is not copied
extraTOML tableempty tableNested keys begin with ASCII letter or _, then letters, digits, or _page.extra

index.page has no default weight and is excluded from sibling ordering unless it has a numeric weight.

draft = true keeps an unfinished page out of an ordinary build and every relationship derived from it, including links, collections, feeds, sitemaps, and search. Use heine serve --drafts to preview it in its real site context. When a published Markdown or template reference names an excluded draft, its checked diagnostic names the draft source path and state. A local heine serve --drafts preview can include the target when it has an effective template. draft = false is a checked error because absence already means published, and _directory.toml cannot declare draft because publication state is local to one page. A draft's declared content paths remain reserved from copied assets, but their files, metadata, template, and Markdown are checked only in that preview.

published and updated must include both a calendar date and a clock time, without a UTC offset. A bare TOML date and an offset-bearing timestamp are rejected; Heine resolves the local time through site.time_zone before exposing UTC RFC 3339 text to templates.

Sibling navigation

The preceding page fields define one page's metadata and output. The following directory-local relationship is exposed through the template values listed later in this reference.

Sibling navigation is a directory-local sequence, independent of collections. For each locale and immediate page directory, Heine includes every rendered page with a numeric weight. It sorts them by ascending weight and then by page ID, so equal weights have a stable order. A page without a numeric weight, including a non-index page with weight = false, does not participate. index.page also needs an explicit numeric weight to participate.

siblings() returns all other participating page IDs in the same order. The optional id argument selects an exact rendered page; locale= is allowed only with id=. sibling_neighbors() returns the immediate values around the current authored page as before and after: the preceding and following members of the sibling sequence. Either is null at an end. It fails when the current page does not participate in sibling ordering.

{% set neighbors = sibling_neighbors() %}
{% if neighbors.before %}
  <a href="{{ neighbors.before.url }}">Previous</a>
{% endif %}
{% if neighbors.after %}
  <a href="{{ neighbors.after.url }}">Next</a>
{% endif %}

Use a collection when a listing needs its own configured ordering; sibling navigation deliberately has one fixed directory-and-weight model.

Output filenames

Rendered pages, like copied assets, must derive portable output filename components. They cannot use empty components, ., .., Windows device names, trailing dots or spaces, or <, >, :, ", /, \, |, ?, *, or control characters. Heine rejects output paths that differ only by case, so a published tree does not depend on the deployment filesystem's case-sensitivity policy. It also rejects NFC-equivalent Unicode spellings, such as composed and decomposed forms of café. Use one NFC-normalized spelling; Heine preserves that literal spelling rather than silently rewriting it. A page with template = false has no output path and is not subject to this output rule.

Within each content tree, template tree, and locale-resource tree, filenames must likewise be distinct after NFC normalization. Heine preserves their literal spelling, but names both source paths when it finds an ambiguity.

Declared content files

Declared content is loaded but not copied as an asset. .toml files become structured TOML, .json files become structured JSON, and every other file is text. If its first line is <!-- segment: name -->, text becomes named content segments; dotted names create nested values and repeated names become ordered arrays. Markdown links and images may use asset:<locale-root-relative-id> for a checked copied asset; ordinary Markdown URLs are unchanged.

Segment markers are recognized before Markdown is parsed. In a segmented Markdown file, a line that looks like <!-- segment: name --> is therefore a marker even when it appears inside a fenced code block. Keep literal marker examples in an unsegmented input, or phrase them so they are not marker-shaped.

For example, this declared text file begins with a segment marker, so it becomes structured content rather than one text value:

<!-- segment: introduction -->
An introduction.
<!-- segment: questions.title -->
First question.
<!-- segment: questions.item -->
One.
<!-- segment: questions.item -->
Two.

For a page declaring it as main = "questions.md", templates receive page.content.main.introduction, page.content.main.questions.title, and the ordered array page.content.main.questions.item. Segmentation applies only when the first line is a marker. Otherwise the complete file remains one text value.

Markdown

Heine renders Markdown with pulldown-cmark. The markdown filter renders arbitrary trusted text. The markdown(content="…") function reads one named, unsegmented Markdown declaration from the current authored page. Use the function for a page's selected table of contents or margin-footnote source so its heading IDs, local note instances, and page facts agree. The following boundaries are part of the current contract:

BehaviorCurrent rule
MetadataHeine does not parse Markdown front matter. YAML or TOML front matter is ordinary Markdown source; page metadata belongs in the adjacent .page file.
ExtensionsOnly the configured tables, strikethrough, task_lists, and footnotes extensions are enabled. Task-list checkboxes receive an accessible name from their direct authored task text; nested list text is excluded. Empty tasks have no authored name.
Raw HTMLTrusted Markdown HTML is passed through unsanitized. Do not use untrusted Markdown as site input. Search indexes read semantic text and img alternatives from authored raw HTML, but never scrape rendered template HTML.
Heading anchors and table of contentsAn opted-in page table of contents creates IDs only on headings in its selected source when rendered with markdown(content="…"); other Markdown remains unanchored. See table of contents.
Margin footnotesAn opted-in page margin-footnote source replaces ordinary endnotes with checked, numbered local note instances when rendered with markdown(content="…"). References must occur in an ordinary paragraph or heading. See margin footnotes.
Ordinary footnotesWith the footnotes extension, every [^label] reference needs a definition. Otherwise, outside a selected margin-footnote source, Heine preserves pulldown-cmark's ordinary endnote behavior: unreferenced definitions are permitted, and definitions remain where the author placed them and in that source order. Generated ordinary and margin-footnote fragments share the reserved __heine-footnote-… namespace, separate from generated heading fragments. Trusted raw HTML and templates remain responsible for avoiding manually authored id collisions.
Ordinary links and imagesOrdinary URLs, including relative URLs such as ./other.md, are emitted unchanged. Heine does not resolve, convert, or check them.
Checked internal linksIn Markdown links, use page:<id> or page:<locale>:<id> for a rendered page. In links or image sources, use asset:<id> for a copied asset. These forms resolve during the build and report invalid targets at the authored source location.

markdown.math and markdown.highlighting add the optional math and syntax-highlighting behavior described in the heine.toml table. They do not add a general client-side JavaScript or CSS pipeline.

data/

data/ is optional and non-published. Files must be .json or .toml; their extensionless path below data/ becomes a dot-addressable template key. data/site.toml becomes data.site, while data/navigation/main.json becomes data.navigation.main. Each path component and file stem is a simple identifier. Key collisions and symbolic links are rejected. TOML calendar dates and date-times become template strings, so format_date() can format a bare YYYY-MM-DD data value. A configured locale directory such as data/de/ is reserved for locale_data while rendering German pages and never falls back to shared data.

deploy/

deploy/ is optional. Each regular file below it is copied byte-for-byte to the matching output-root path; it is neither an asset nor template input. For example, deploy/.htaccess is published as public/.htaccess, and deploy/google123.html becomes public/google123.html. Use it for host-specific configuration or external verification files, not for files a template needs to link with asset().

Deployment paths use the same UTF-8, symbolic-link, portable-filename, case-collision, Unicode-normalization, reserved-output, and output-collision rules as copied assets. A full build removes output for deleted deployment files; --quick only updates present files and can leave deleted paths stale. See the deployment-files guide for the rationale and examples.

LICENSES/ and asset sidecars

LICENSES/ is optional. Direct .txt files named for an SPDX license or exception identifier, or LicenseRef-…, are copied to <build.output_dir>/LICENSES/. An adjacent copied-asset sidecar named asset.ext.license, or one exact [[licensing.groups]] declaration, supplies SPDX-FileCopyrightText, SPDX-License-Identifier, and optional SPDX-FileComment facts. Sidecars are not copied. Each identifier in an expression must have matching published text; malformed declarations, orphan sidecars, overlapping group members, and a group-sidecar conflict are errors. licensing.required = true requires one such declaration for every copied asset. Groups use literal published output_path values, without a leading slash or site.base_path. See the asset-licensing guide. The .license suffix is reserved for these sidecars and is never copied as an asset.

Each [[licensing.groups]] table has the following strict fields:

FieldTypeDefaultConstraintsEffect
assetsarray of stringsrequiredNon-empty distinct literal copied-asset output_path values; no leading slash or site.base_pathExact published assets that share this record
SPDX-FileCopyrightTextstring or arrayrequiredOne or more non-empty valuesOrdered copyright notices
SPDX-License-Identifierstring or arrayrequiredOne or more non-empty SPDX expressions; an array does not imply AND or OROrdered authored SPDX tag values
SPDX-FileCommentstring or arrayabsentNon-empty values when presentOptional ordered comments

Template contract

Templates use Tera2. Heine provides only the following render-facing values; they are scoped to the locale currently being rendered unless noted otherwise.

ValueFields and meaning
localecode is the configured BCP-47 locale; direction is its configured "ltr" or "rtl" value. Use both on the document element.
pageAn authored page's id, path, filename, dir, subdirs, content, title, description, summary, authors, published, updated, extra, directory, taxonomies, series, toc, footnotes, draft, weight, and translations; null for generated templates. path and filename are absent without rendering.
page.drafttrue for an authored draft included through heine serve --drafts, otherwise false. It never appears for a generated template. See drafts.
page.tocnull unless the authored page has an effective table-of-contents setting. Otherwise content names the selected declaration and headings is the source-order array of level, depth, text, and fragment. See table of contents.
page.footnotesnull unless the authored page has an effective margin-footnote setting. Otherwise content names the selected declaration. Render that source exactly once through markdown(content="…"). See margin footnotes.
page.directoryid, title, description, summary, and extra from the immediate directory descriptor.
page.translationsKnown counterparts keyed by locale code; each has id and output-relative path.
page.taxonomiesAssigned terms keyed by taxonomy name. Each term has literal name plus base-path-aware url and current-output-relative relative_url.
page.seriesAuthored-order Series memberships. Each has id, Fluent-resolved title, optional description, authored position, resolved one-based number, total, base-path-aware url, current-output-relative relative_url, and optional membership-local previous and next page links. See Series.
taxonomynull for authored pages. A taxonomy index receives name and ordered terms; a term listing also receives term. Each term has name, count, url, relative_url, and explicitly configured counterparts, keyed by locale code.
seriesnull for authored pages. A generated Series index has id, title, optional description, count, URLs, and local non-empty Series entries. A generated listing has id, title, optional description, count, URLs, and ordered page_ids.
dataShared values from data/.
locale_dataValues from data/<locale>/; it never falls back to shared data.
rootRelative prefix from the rendered page to the site root.
paginationnull for ordinary pages; the current generated-listing view otherwise, including first_item_number for continuing ordered-list markers across pager pages. See pagination.

page.dir is the locale-relative containing directory, or the empty string for a page at the locale root. page.subdirs is its sorted immediate list of source subdirectory names. They describe the source-tree location; they do not discover pages or create output.

Combine root with a counterpart's path for a relative language-switcher link, or pass an exact locale and ID to page() for its base-path-aware URL. All Heine functions check their authored inputs and fixed keyword names at the template call site. The additional keyword names accepted by t() are Fluent message arguments. Heine checks their value types while Fluent formats the selected message; a message may deliberately ignore an argument it does not use.

Template inheritance and components use Tera2's own syntax; the tutorial shows one component. Heine does not provide a configuration or plugin hook for registering site-defined Rust filters or functions. The function and filter tables below are the complete Heine additions to a template environment.

FunctionUseResult
assetasset(id="assets/logo.svg")A copied asset in the current locale: url, relative_url, optional integrity, width, height, and optional licensing (copyrights, expressions, comments, license_texts). Shared assets use the assets/ prefix.
attributionsattributions()Deterministic inventory of assets with resolved licensing declarations. Each item has asset (output_path, url, relative_url) and licensing (copyrights, expressions, comments, license_texts). Each license text has id, url, and relative_url; output_path is the locale-qualified published path, not an asset() lookup ID.
pagepage(id="guide/install")A rendered page in the current locale, including its render-facing metadata, content, and url / relative_url.
pagepage(locale="de", id="hilfe/installieren")An exact rendered page in the named configured locale; this never guesses a translation counterpart.
markdownmarkdown(content="main")Trusted HTML from the named declared, unsegmented Markdown content of the current authored page. It applies matching heading IDs and checked local margin-footnote structure when that content is selected by either feature.
page_existspage_exists(id="guide/index")Whether a rendered page exists in the current locale. It returns false for a missing page, but invalid IDs and locales still fail at the call site.
collectioncollection(name="posts")A configured current-locale collection with name, count, and ordered page_ids.
collection_neighborscollection_neighbors(name="posts")Immediate rendered-page views around the current authored page in the named current-locale collection order. before is the preceding member and after the following member; either is null at an end. It fails if the collection is unknown or the current page is not a member.
searchsearch(name="site") or search(name="site", locale="de")A configured JSON search index for the current or exact configured locale: name, selected-document count, base-path-aware url, and current-output-relative relative_url. Invalid or unknown names and locales fail at the call site.
feedfeed(name="posts") or feed(name="posts", locale="de")A configured Atom feed for the current or exact configured locale: name, Fluent-resolved title, base-path-aware url, and current-output-relative relative_url. Invalid or unknown names and locales fail at the call site.
taxonomytaxonomy(name="tags") or taxonomy(name="tags", locale="de")A configured taxonomy index in the current or an exact configured locale, with name, base-path-aware url, and current-output-relative relative_url. Invalid or unknown names and locales fail at the call site.
seriesseries() or series(id="getting-started")The current locale's generated Series index, or one non-empty local Series. locale= selects an exact configured locale. An invalid ID, disabled Series, invalid locale, or direct lookup of an empty local Series fails at the call site.
series_has_membersseries_has_members(id="getting-started") or series_has_members(id="getting-started", locale="de")Whether a configured Series has local members in the current or selected exact locale. It returns false only for an empty local Series; invalid IDs, locales, and disabled Series fail at the call site.
siblingssiblings() or siblings(id="blog/index")Ordered IDs for the other eligible pages in the selected page’s directory. See sibling navigation. locale= is allowed only with id=.
sibling_neighborssibling_neighbors()Immediate rendered-page views around the current authored page in directory sibling order. before is the preceding member and after the following member; either is null at an end. It fails if the current page has no numeric sibling weight. See sibling navigation.
tt(id="entry-count", count=entries | length)Escaped Fluent text for the current locale. It falls back to the default locale only when the message or requested attribute is absent. Use attribute="label" for a Fluent attribute; other named arguments must be strings, numbers, or booleans.
format_dateformat_date(value=page.published, style="long")A locale-formatted calendar date. Values are RFC 3339 timestamps, such as page.published, or bare YYYY-MM-DD values supplied by template data; styles are short, medium (default), and long.
highlight_csshighlight_css()The base-path-aware URL for the configured generated highlighting stylesheet. It fails if highlighting is disabled.
pagination_linkspagination_links()Every lightweight pager link for the current paginated listing. It fails at the call site outside such a render.

asset() IDs and page() IDs are relative to the current locale tree and never begin with /. Assign a function result with {% set guide = page(id="guide") %} before reading a field such as guide.url; Tera does not support a field access directly on a function call. asset() can resolve a shared asset such as assets/logo.svg; a non-default locale can override it below its own assets/ directory. page() resolves only rendered pages.

IDs are literal source filenames, not URL fragments: do not pre-encode spaces, #, %, or non-ASCII characters. Heine percent-encodes a resolved output path exactly once when it exposes url or relative_url. For non-ASCII names, use the same NFC-normalized spelling as the filename on disk; Heine preserves that literal spelling rather than normalizing lookup IDs.

highlight_css() returns the base-path-aware URL for a stylesheet that Heine generates at markdown.highlighting.stylesheet. Its content comes from the configured light and dark Giallo themes and includes the corresponding prefers-color-scheme: dark rule; it is not a copied or user-authored asset. It is available only when [markdown.highlighting] is configured.

FilterInputResult
markdowntextTrusted HTML rendered under [markdown] settings. It cannot render an exact selected table-of-contents or margin-footnote source; use markdown(content="…") for that page content.
latestcopied asset IDURL for the highest versioned matching asset
dimensionscopied asset IDwidth and height for an image, or no dimensions for a known non-image

For latest and dimensions, a relative input is resolved from page.dir; a leading / makes it locale-root-relative.