Why I Added Mermaid to My Documentation
I run a self-hosted wiki for my homelab documentation. For years, I documented network diagrams, workflow sequences, and system architectures using external tools—draw.io files, screenshots from Visio, even hand-drawn sketches photographed and uploaded. Every time I needed to update a diagram, I had to open the original file, make changes, export an image, and re-upload it. Half the time I couldn’t find the source file, so I’d redraw from scratch.
The breaking point came when I was documenting my Docker networking setup across three Proxmox hosts. I made a diagram, saved it as a PNG, then realized I’d forgotten a VLAN. Starting over felt ridiculous. I needed diagrams that lived in the same markdown files as my documentation—text I could edit directly without leaving my editor.
That’s when I looked into Mermaid. It renders diagrams from plain text syntax, right in the browser. No external tools, no image files to manage, no broken links when I reorganize folders.
My Setup: BookStack with Custom JavaScript
I use BookStack as my self-hosted wiki. It runs in a Docker container on one of my Proxmox VMs, behind Nginx Proxy Manager. BookStack supports custom HTML head content, which meant I could inject the Mermaid library without modifying the application itself.
I added this to the custom HTML head section in BookStack’s settings:
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true, theme: 'dark' });
</script>
I used the CDN version initially because I wanted to test before committing to self-hosting the library. The startOnLoad: true option tells Mermaid to automatically find and render any code blocks with the mermaid class when the page loads. I set the theme to dark because my BookStack instance uses a dark theme, and the default light theme looked jarring.
In my markdown pages, I write diagrams like this:
```mermaid
graph TD
A[Proxmox Host] --> B[Docker VM]
B --> C[BookStack Container]
B --> D[n8n Container]
BookStack renders the code block with a mermaid class, and the Mermaid library picks it up and converts it to an SVG diagram.
What Worked
The integration was surprisingly straightforward. Within ten minutes of adding that script tag, I had working diagrams rendering on every page. I didn’t need to modify BookStack’s Docker image, install plugins, or mess with the database.
I started using Mermaid for network topology diagrams, showing how my VLANs connect across switches and firewall rules. Sequence diagrams became useful for documenting API workflows in my n8n automations—showing which service calls which, in what order, and what happens on failure.
The text-based format meant I could version control my documentation properly. When I push my BookStack markdown exports to a Git repository, the diagram definitions are just text. I can see exactly what changed in a diff, unlike binary image files.
Editing became faster. I’d open a page, click edit, change a node name or add an arrow, and save. No context switching to another application. No file management overhead.
What Didn’t Work
The CDN approach had an obvious problem: if my internet connection dropped or jsdelivr went down, my diagrams wouldn’t render. For a self-hosted setup, that dependency felt wrong. I wanted everything local.
I downloaded the Mermaid library and tried hosting it from BookStack’s public directory. BookStack doesn’t make this easy—it’s not designed to serve arbitrary static files. I ended up creating a separate Nginx location block in my reverse proxy config to serve the Mermaid files from a mounted volume. It worked, but it felt like a hack. I had to remember to update the files manually when new Mermaid versions came out.
The syntax took time to learn. Mermaid supports many diagram types—flowcharts, sequence diagrams, Gantt charts, entity-relationship diagrams—but each has its own syntax quirks. I spent an hour trying to figure out why my flowchart arrows weren’t rendering, only to discover I’d used -> instead of -->. The error messages weren’t helpful; diagrams just wouldn’t appear, with no indication why.
Complex diagrams became hard to maintain. I documented my entire Docker Compose stack in one large flowchart, and it turned into an unreadable mess of nodes and arrows. The text definition was over 100 lines, and making changes required careful attention to not break the syntax. I learned to keep diagrams small and focused.
Dark mode theming wasn’t perfect. While Mermaid has a dark theme option, some diagram elements still used light colors that clashed with my BookStack theme. I had to add custom CSS to override specific Mermaid classes, which meant digging through the rendered SVG to find the right selectors.
Self-Hosting the Library
After a few weeks of using the CDN version, I moved to fully self-hosted files. I created a simple Nginx container specifically for serving static assets like Mermaid, Font Awesome, and other JavaScript libraries I use across different services.
The Nginx config is minimal:
server {
listen 80;
server_name assets.internal.home;
root /usr/share/nginx/html;
location / {
add_header Cache-Control "public, max-age=31536000";
}
}
I mounted a local directory to /usr/share/nginx/html and dropped the Mermaid files there. Then I updated my BookStack custom HTML to point to https://assets.internal.home/mermaid/mermaid.esm.min.mjs instead of the CDN.
This setup gave me full control. No external dependencies, no tracking, no surprise breaking changes when a CDN updates their files. The downside is I have to manually update the library, but I only do that when I need a new feature or bug fix.
Practical Diagram Types I Actually Use
I thought I’d use every diagram type Mermaid offers, but in practice, I stick to three:
Flowcharts for system architecture and decision trees. I use these to document how traffic flows through my network, which firewall rules apply where, and how my backup scripts decide what to back up.
Sequence diagrams for API interactions and automation workflows. These are invaluable for documenting my n8n workflows, showing the order of HTTP requests, webhook triggers, and error handling paths.
Entity-relationship diagrams for database schemas. I don’t use these often, but when I do, they’re clearer than trying to describe table relationships in prose.
I tried Gantt charts for project planning but found them too rigid. I tried state diagrams for documenting service states but found simple flowcharts more intuitive. Mermaid supports many diagram types, but most felt like solutions looking for problems in my use case.
Key Takeaways
Mermaid solved my diagram maintenance problem. I no longer lose source files or deal with image export workflows. Diagrams live in my documentation as editable text.
The learning curve is real. Each diagram type has its own syntax, and error messages are unhelpful. I keep the Mermaid documentation open in a browser tab and reference it constantly.
Self-hosting the library is worth the extra setup. Relying on a CDN for self-hosted documentation defeats the purpose of self-hosting.
Keep diagrams simple. Large, complex diagrams are hard to maintain in text format. I break them into smaller, focused diagrams that document one thing well.
Not every wiki or documentation platform makes this easy. BookStack’s custom HTML head feature made integration trivial. Other platforms might require plugins, theme modifications, or custom builds. Check before committing to Mermaid.