Mermaid Diagrams
This theme renders Mermaid diagrams from standard fenced code blocks. Just label the fence with mermaid and write the diagram source — no shortcodes required.
How it works
Authoring
Write a fenced code block with the mermaid info string. No front-matter flag, no shortcode:
```mermaid
flowchart LR
A --> B
```What Zola emits
With syntax highlighting enabled ([markdown.highlighting] in config.toml), Zola tags the code element with data-lang="mermaid" and wraps each line in spans:
<pre class="..." style="..."><code data-lang="mermaid"><span class="..."><span>flowchart LR</span></span>
<span class="..."><span> A --> B</span></span></code></pre>
If you disable highlighting, you'd get the plainer <code class="language-mermaid"> form instead. The init script handles both.
Runtime pipeline
static/js/mermaid-init.js runs on every page (deferred). On pages without diagrams it does nothing — Mermaid itself only loads when needed:
var blocks = document.querySelectorAll(
'pre code[data-lang="mermaid"], pre code.language-mermaid'
);
if (blocks.length === 0) return;
For each match, the highlighted <pre> is replaced with a clean container so Mermaid can take over. textContent strips the highlighter's <span> wrappers and decodes entities (--> → -->):
blocks.forEach(function (code) {
var pre = code.parentElement;
var container = document.createElement('div');
container.className = 'mermaid';
container.textContent = code.textContent;
pre.replaceWith(container);
});
Mermaid is then loaded on demand from the vendored bundle. The URL is passed through a meta tag in base.html so Zola's get_url can resolve it correctly under any base_url:
<meta name="mermaid-src" content="{{ get_url(path='js/mermaid.min.js') }}">var script = document.createElement('script');
script.src = document.querySelector('meta[name="mermaid-src"]').content;
script.onload = function () { renderAll(); /* ... */ };
document.head.appendChild(script);Theme integration
The theme option is derived from <html class="dark"> at render time:
function currentTheme() {
return document.documentElement.classList.contains('dark') ? 'dark' : 'default';
}
window.mermaid.initialize({
startOnLoad: false,
theme: currentTheme(),
securityLevel: 'strict'
});
A MutationObserver on <html>'s class attribute re-renders all diagrams when you toggle dark/light. Each container's original source is cached on dataset.mermaidSource so the second render can reset innerHTML and clear Mermaid's data-processed flag:
var observer = new MutationObserver(function (mutations) {
for (var i = 0; i < mutations.length; i++) {
if (mutations[i].attributeName === 'class') {
renderAll();
return;
}
}
});
observer.observe(document.documentElement, {
attributes: true,
attributeFilter: ['class']
});Why vendor mermaid.min.js?
Zola themes are installed as a git submodule and built without Node.js, so anything the browser needs has to live in static/. The bundle is ~3 MB but only fetched on pages that contain a diagram, so non-diagram posts pay zero cost beyond the tiny init script.
Flowchart
flowchart LR
A[Start] --> B{Is it working?}
B -->|Yes| C[Ship it]
B -->|No| D[Debug]
D --> BSequence Diagram
sequenceDiagram
participant Reader
participant Browser
participant Mermaid
Reader->>Browser: Open post
Browser->>Browser: Detect mermaid code blocks
Browser->>Mermaid: Load mermaid.min.js
Mermaid-->>Browser: Render SVG
Browser-->>Reader: Display diagramClass Diagram
classDiagram
class Animal {
+String name
+int age
+makeSound() void
}
class Dog {
+String breed
+bark() void
}
class Cat {
+bool indoor
+purr() void
}
Animal <|-- Dog
Animal <|-- CatState Diagram
stateDiagram-v2
[*] --> Draft
Draft --> Review : submit
Review --> Draft : changes requested
Review --> Published : approve
Published --> Archived : retire
Archived --> [*]Entity Relationship Diagram
erDiagram
POST ||--o{ COMMENT : has
POST ||--o{ TAG : tagged-with
POST {
string title
string slug
date published
}
COMMENT {
string author
string body
date posted
}
TAG {
string name
}Gantt Chart
gantt
title Blog Theme Roadmap
dateFormat YYYY-MM-DD
section Core
Search :done, s1, 2026-01-01, 30d
Dark mode :done, s2, 2026-02-01, 14d
section Content
Mermaid support :active, c1, 2026-05-01, 7d
Math (KaTeX) : c2, after c1, 14dPie Chart
pie title Time spent writing posts
"Outlining" : 20
"Drafting" : 50
"Editing" : 25
"Wrestling with Markdown" : 5Git Graph
gitGraph
commit id: "init"
commit id: "search"
branch feature/mermaid
checkout feature/mermaid
commit id: "vendor mermaid.js"
commit id: "init script"
checkout main
merge feature/mermaid
commit id: "next feature"Mindmap
mindmap
root((Zola Devin))
Content
Posts
Tags
Comments
Theming
Dark mode
Tailwind
Features
Search
RSS
MermaidTimeline
timeline
title Theme milestones
2025 : Project started
: Tailwind integration
2026 : Search added
: Dark mode default
: Mermaid diagrams
That's a sampling of what's available. See the Mermaid docs for the full diagram catalogue and syntax.