Docouture

Integrations

Build-time and content capabilities that ship with every scaffolded site — as opposed to UI Bundle's site chrome, or Custom AsciiDoc components's authoring blocks. Grouped by what they’re for.

Authoring & content

Diagrams — Kroki

[mermaid], [plantuml], [graphviz], [bpmn], [excalidraw] and over a dozen more diagram languages (see @inditextech/docouture-asciidoc-extensions’ `lib/kroki-config.js for the full, live-verified list) render as real diagrams via a self-hosted Kroki service, enabled by default (kroki-enabled: true, kroki-diagram-types in antora-playbook.yml — see Antora Playbook). The service starts itself automatically the first time a build needs it (Docker required); docouture teardown kroki stops it, docouture eject kroki copies its compose definition out for customization. Mermaid diagrams get this site’s own theming baked in server-side.

The classic asciidoctor-diagram/asciidoctor-kroki positional shorthand works — [plantuml,architecture,png] resolves target/format from position, same as [plantuml,format=png] — alongside jpeg/pdf/base64 raster formats and a txt/atxt/utxt text-rendering family (Kroki’s own ASCII-art-style output, no image at all), each gated per diagram type against what Kroki’s own server actually accepts. Any named attribute beyond the built-in set is forwarded to Kroki as a diagram-specific option (e.g. [structurizr,view-key=SystemContext]). Without Docker, or with the feature disabled, a diagram block renders as its own literal source text rather than failing the build. role=zoom-in (also honored on a plain image:: block) adds a click-to-zoom fullscreen overlay. Full syntax: Custom AsciiDoc components.

Syntax highlighting — Shiki

source-highlighter: shiki in antora-playbook.yml switches every code block from Antora's own client-side default (highlight.js) to build-time, static highlighting. `@inditextech/docouture-antora-extensions’ Shiki prewarm step builds the highlighter once up front rather than per-block.

Changelog pages

Changelog's per-version sections are generated at build time from code/CHANGELOG.md, not hand-copied: @inditextech/docouture-antora-extensions parses every cut [x.y.z] section, converts its # Section headings and - [#PR](url) text bullets to AsciiDoc, and appends each one as a == vX.Y.Z section directly onto whatever page already lives at changelog/index.adoc — only on a site that has one; a site with no changelog page is left untouched.

## [Unreleased] is handled differently from a real cut release: it never becomes a == vX.Y.Z section (Keep a Changelog doesn’t consider "unreleased" a version either), but its content still renders as a plain == Unreleased section — and only on the component version Antora resolved as prerelease (the version built from main, never itself tagged). Any real, tagged release’s own changelog page never shows it: a tag is an immutable snapshot, and [Unreleased] is by definition whatever has landed on main since. An empty [Unreleased] heading (nothing merged since the last cut) renders no section at all rather than an empty one.

The file is read once per build, off disk, applied identically to every component version being built — not resolved per-ref through git, so a real release tag’s own changelog page reflects whatever code/CHANGELOG.md says on disk right now, not that tag’s own historical copy of the file. In practice this only matters for the cut releases: a tagged version’s page shows every ## [x.y.z] section on disk, no more and no less, regardless of which ref cut it. Override the default code/CHANGELOG.md location (resolved relative to the playbook’s own directory) with changelog_path on the extension’s registration entry:

antora:
  extensions:
    - require: '@inditextech/docouture-antora-extensions'
      changelog_path: ../code/CHANGELOG.md

@inditextech/docouture-antora-extensions builds a search index at build time, published per component version, that the UI bundle’s search dialog reads directly (UI Bundle). No manual wiring — registering the extension is enough.

AI ingestion — llms.txt

Every build publishes llms.txt (a Markdown index) and llms-full.txt (a full aggregated Markdown dump) at the site root, alongside sitemap.xml — the llms.txt convention, letting an agent read the site without scraping rendered HTML. Configured under docs/src/antora.yml’s `llms key (see Antora Descriptor) — summary becomes the blockquote under the site title; exclude leaves specific pages out of both files. See also AI-First approach for the broader philosophy this feeds into.

Site reliability & URLs

A scaffolded site ships scripts/check-links.mjs (via linkinator) and a check-links npm script. package.json’s own `docouture.checkLinks.ignore is a list of URL globs to skip — pre-seeded with this repository’s own URL, so a build doesn’t fail checking a link to itself before it’s ever been published.

URL routing: the /latest/ alias

Rather than Antora’s own urls.latest_version_segment (whose default replace strategy turns one real version segment into a permanent redirect stub the moment a release exists — see Versioning modes), duplicate_latest_version: true on the antora.extensions registration entry republishes whichever version Antora computes as latest a second time, under /latest/…, as a genuinely independent copy — so both the real version segment and /latest/ stay real content.

Legacy URL redirects

For a site migrated from another documentation tool, arbitrary literal legacy URLs can redirect to whatever real page now answers the equivalent URL — configured as from/to URL templates on the @inditextech/docouture-antora-extensions registration entry itself (not antora.yml, since these apply across every ref a build aggregates, not per-version):

antora:
  extensions:
    - require: '@inditextech/docouture-antora-extensions'
      redirects:
        - from: '/docs/main/old-page'
          to: '/main/new-page'
        - from: '/docs/**'
          to: '/main/**'

* captures one path segment, captures the remainder. Rules are first-match-wins in authoring order — an exact override belongs ahead of a broad catch-all.