Search indexes
Heine can generate a locale-local JSON document index from one or more collections. It supplies checked membership, stable page facts, source-derived text, URLs, and output ownership. Your site supplies the browser search engine and user interface.
This keeps search independent of one JavaScript library. A small site can use a local script, while a larger one can replace that script with a suitable browser library without changing the generated document contract.
Create an index
Start with a configured collection, then add a named search index:
[collections.posts]
order = "published-desc"
[search.site]
collections = ["posts"]
path = "search/site.json"
collections must name one or more distinct configured collections. path
must use the literal lowercase .json suffix. Heine unions members for each
locale, removes duplicates, and orders the documents by page ID. The default
locale receives search/site.<hash>.json; each other locale receives the same
path below its locale prefix.
The filename includes the complete SHA-256 digest of the serialized JSON by
default. A new index therefore has a new immutable URL when its contents
change. Set versioned = false only when a stable endpoint is necessary and
your deployment rechecks its cache.
Use the checked template view
Expose an index URL through search(), rather than constructing a path in a
template:
{% set index = search(name="site") %}
<form data-search-url="{{ index.url }}">
<input type="search" name="q">
</form>
The view contains name, count, base-path-aware url, and
current-output-relative relative_url. search(name="site", locale="de")
selects one exact configured locale. Unknown names and invalid locale values
fail at the template call site.
Document contents
The current JSON envelope schema is format 3. Each document has stable
metadata, including draft. It is false in an ordinary index and true
only for a draft included through heine serve --drafts, so a
site-owned preview interface can label it. Its sections array contains
source-derived text from every declared Markdown input of its page. A section
has text and a fragment: the fragment is null unless that text begins at
a heading with an existing generated table-of-contents identifier. A browser
can therefore link a matching section directly, while a page without such a
heading remains linkable at its ordinary page URL.
Markdown text, headings, link labels, image alternatives, code, and recognized
math source contribute. Authored raw HTML contributes semantic text nodes and
img alternatives, but not markup, URLs, comments, attributes, or the
contents of script, style, and template. This means an Arabic quotation
inside trusted raw HTML remains searchable as authored Unicode text, even on
an English page. Heine does not inspect rendered HTML, templates, copied
assets, or an inferred content.main body. See the
reference for the full JSON shape and extraction
rules.
Browser behavior belongs to the site
The starter site includes a dependency-free example that fetches the index, uses basic Unicode-aware local substring matching, safely creates DOM nodes, and stores its query and result page in the URL. It is a usable starting point, not a required ranking policy or a bundled Heine component.
Search indexes are rebuilt by full builds and heine serve. --quick leaves
the previously published index unchanged, because it cannot safely establish
complete collection membership after every possible source change.