Adding Mermaid Diagrams to Hugo Sites
When writing technical documentation or blog posts, visual diagrams can significantly enhance content clarity.
Mermaid is a popular JavaScript library that renders diagrams and flowcharts from simple text definitions, making it perfect for markdown-based Hugo sites.
Mermaid allows you to create various diagram types using simple syntax:
- Flowcharts and process diagrams
- Sequence diagrams for system interactions
- Gantt charts for project timelines
- Git branch diagrams
- Entity relationship diagrams
The Problem with Existing Tutorials
A quick web search reveals 4-5 tutorials on integrating Mermaid with Hugo. However, none worked out of the box for me across different Hugo themes. Common issues include:
- Auto-detection methods that fail to find code blocks
- Theme-specific implementations that break with updates
- Loading Mermaid on every page regardless of need
- Incompatibility with Hugo’s goldmark renderer
This article presents a working method that I use to enable Mermaid across themes, keeping things simple yet efficient when it comes to page loading.
The Working Solution
Step 1: Enable Unsafe HTML Rendering
First, ensure Hugo can render the JavaScript properly by adding this to your config.yaml
:
markup:
goldmark:
renderer:
unsafe: true
Or in config.toml
:
[markup]
[markup.goldmark]
[markup.goldmark.renderer]
unsafe = true
Step 2: Create the Mermaid Partial
Create layouts/partials/mermaid.html
:
{{ if .Params.mermaid }}
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Look for mermaid code blocks
const mermaidBlocks = document.querySelectorAll('pre code.language-mermaid');
if (mermaidBlocks.length > 0) {
mermaid.initialize({
startOnLoad: false,
theme: 'default',
flowchart: {
useMaxWidth: true
}
});
mermaidBlocks.forEach((block, index) => {
const graphDefinition = block.textContent;
const div = document.createElement('div');
div.className = 'mermaid';
div.innerHTML = graphDefinition;
block.parentNode.parentNode.replaceChild(div, block.parentNode);
});
mermaid.init();
}
});
</script>
{{ end }}
Step 3: Include the Partial in Your Base Template
Add the following to your layouts/_default/baseof.html
just before the closing </body>
tag:
<!DOCTYPE html>
<html lang="{{ with .Site.LanguageCode }}{{ . }}{{ else }}en-US{{ end }}">
{{- partial "head.html" . -}}
<body>
{{- partial "preloader.html" . -}}
{{- partial "header.html" . -}}
{{- block "main" . }}{{- end }}
{{- partial "footer.html" . -}}
{{ partial "mermaid.html" . }}
</body>
</html>
Step 4: Usage in Content
To use Mermaid diagrams, simply add mermaid: true
to your front matter:
---
title: "My Technical Post"
date: 2025-05-04T14:30:00+08:00
mermaid: true
---
# System Architecture
Here's our deployment flow:
```mermaid
graph TD
A[Developer] -->|Push Code| B[GitHub]
B -->|Webhook| C[Cloudflare Pages]
C -->|Build| D[Hugo Site]
D -->|Deploy| E[Production]
style A fill:#e1f5fe
style E fill:#c8e6c9
And a sequence diagram:
Performance Benefits
By using front matter control (mermaid: true
), you ensure:
- Mermaid JavaScript only loads when needed
- Faster page loads for content without diagrams
- Clear indication of which pages use diagrams
- No impact on SEO or Core Web Vitals for diagram-free pages
Example Diagrams
Here’s what you can create:
This approach has served me well across multiple Hugo themes and projects.
Hope this helps!