Diagrams in Templates

The diagram() template function renders a diagram inline from a Jinja expression. Use it when the diagram source comes from frontmatter, a layout context, or a shared template file rather than the page body. Fenced code blocks handle the in-content case; this function fills the gap for theme authors, and it is where caption, alt text, and the other options live.

Both author paths route through the same renderer and cache, so the rendered SVG is byte-identical for the same source.

Quick reference

diagram(type, source, *, width=None, height=None, theme=None,
        caption=None, alt=None, class=None, render=None) -> safe html
ArgKindDescription
typepositionalRenderer language: mermaid, svgbob, bob, or a plugin-registered language
sourcepositionalRaw diagram source text (a string, not a path)
width / heightkeywordSVG dimensions in pixels
themekeywordRenderer theme name (defaults to config.diagrams.renderers.<type>.theme)
captionkeywordRendered as <figcaption> inside a wrapping <figure>
altkeywordForwarded as the SVG’s <title> for screen readers
classkeywordExtra CSS class appended to the wrapper
renderkeywordPer-block render-mode override: server, client, or hybrid

Setting any of caption, alt, or class flips the wrapper from a bare <div class="diagram-wrapper"> to <figure>; otherwise the SVG is wrapped in a div, which is what a fenced block emits too – so a theme rule written for one path applies to the other.

Frontmatter-driven diagrams

The most common use: a page declares its diagram in frontmatter, the template renders it. This keeps the diagram source close to the page data without polluting the rendered markdown.

---
title: Architecture Overview
architecture_diagram: |
  flowchart LR
    Browser --> Accent
    Accent --> Markdown
architecture_alt: A request flow from browser through Accent to markdown
---
{% if page.custom.architecture_diagram %}
  {{ diagram("mermaid", page.custom.architecture_diagram,
             caption="Architecture",
             alt=page.custom.architecture_alt) }}
{% endif %}

Note the use of page.custom.<field> (Accent’s frontmatter passthrough namespace) rather than page.meta.<field>.

Hardcoded diagrams in templates

Sometimes a layout template wants its own diagram (e.g., a “how the build pipeline works” overview rendered on every docs index page). A literal string works fine:

{{ diagram("mermaid",
           "flowchart LR\n  Author --> Template\n  Template --> SVG",
           caption="Author path: template function") }}

\n in a double-quoted Jinja string is a real newline at runtime, so the example above produces a three-line Mermaid program.

Error handling

diagram() honours diagrams.on_error from config.yaml:

ModeBehaviour
warn (default)Renders an inline warning-box SVG and keeps the page rendering
failRaises a MiniJinja error so accent build exits non-zero
silentEmits an empty string

Unknown renderer types (e.g., diagram("unknown-lang", "...")) follow the same matrix.

Dev-overlay click-to-editor

The dev-mode source-provenance overlay routes clicks on diagrams back to their source file. Fenced blocks get this treatment because the renderer knows which markdown file they came from. The diagram() template function receives a bare source string – it could have come from frontmatter, a literal, or a layout context – so there is no single source path to attribute, and template-function diagrams are intentionally skipped by the overlay. Cache correctness is unaffected because cache keys hash the source content directly.

See also

  • The Diagrams page in the Markdown Guide documents the full renderer surface (Mermaid dialects, Svgbob, plugin languages, configuration, render modes).
  • A fenced ```mermaid block is the in-content equivalent for prose pages; it takes no options beyond render.
  • templates/partials/diagram-fn-example.html.jinja in the default theme is a working demonstration of both hardcoded-source and frontmatter-driven calls.