Add Mermaid to Hugo with Dark Mode

Recently, I was revisiting materials in Deep Learning. I need tools that generate diagrams easily. Drawing the graphs from scratch and upload them individually to the image hosting platform is a daunting process. This is when Mermaid comes into rescue. Now I can generate diagrams directly using Markdown. Here’s how to do it inside a Hugo site.

I use the etch theme, but this process should apply to all sites using Hugo. First, we create a new file /layouts/shortcodes/mermaid.html. We fill up mermaid.html with:

<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
<script>
    let isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
    let mermaidTheme = (isDark) ? 'dark' : 'default';
    let mermaidConfig = {
        theme: mermaidTheme,
        logLevel: 'fatal',
        securityLevel: 'strict',
        startOnLoad: true,
        arrowMarkerAbsolute: false,

        er: {
            diagramPadding: 20,
            layoutDirection: 'TB',
            minEntityWidth: 100,
            minEntityHeight: 75,
            entityPadding: 15,
            stroke: 'gray',
            fill: 'honeydew',
            fontSize: 12,
            useMaxWidth: true,
        },
        flowchart: {
            diagramPadding: 8,
            htmlLabels: true,
            curve: 'basis',
        },
        sequence: {
            diagramMarginX: 50,
            diagramMarginY: 10,
            actorMargin: 50,
            width: 150,
            height: 65,
            boxMargin: 10,
            boxTextMargin: 5,
            noteMargin: 10,
            messageMargin: 35,
            messageAlign: 'center',
            mirrorActors: true,
            bottomMarginAdj: 1,
            useMaxWidth: true,
            rightAngles: false,
            showSequenceNumbers: false,
        },
        gantt: {
            titleTopMargin: 25,
            barHeight: 20,
            barGap: 4,
            topPadding: 50,
            leftPadding: 75,
            gridLineStartPadding: 35,
            fontSize: 11,
            fontFamily: '"Open-Sans", "sans-serif"',
            numberSectionStyles: 4,
            axisFormat: '%Y-%m-%d',
            topAxis: false,
        },
    };
    mermaid.initialize(mermaidConfig);
</script>

This setup allows us to change Mermaid-generated diagrams’ theme based on the website’s current (light/dark) theme. This configuration is borrowed from the Setup.md from mermaid-js (except the theme part). You can find more information there about configuring mermaid.

You can also do this in /partials, but it will slow down the loading time because the mermaid js file is always loaded, regardless whether you are actually using mermaid.

Next, we add the follow lines to the file /layouts/shortcodes/mermaid.html:

<center>
<div class="mermaid">
    {{.Inner}}
</div>
</center>

Feel free to remove the <center> tag if you want to customize the diagram’s layout. And… we are done!

Here is an example sequenceDiagram. You should see that this diagram will adjust its theme accordingly based on light/dark mode. We use the example code from mermaid doc (just uncomment mermaid in the shortcode {{/*< mermaid >*/}}):

{{/*< mermaid >*/}}
sequenceDiagram
    participant Alice
    participant Bob
    Alice->>John: Hello John, how are you?
    loop Healthcheck
        John->>John: Fight against hypochondria
    end
    Note right of John: Rational thoughts <br/>prevail!
    John-->>Alice: Great!
    John->>Bob: How about you?
    Bob-->>John: Jolly good!
{{/*< /mermaid >*/}}
sequenceDiagram participant Alice participant Bob Alice->>John: Hello John, how are you? loop Healthcheck John->>John: Fight against hypochondria end Note right of John: Rational thoughts
prevail! John-->>Alice: Great! John->>Bob: How about you? Bob-->>John: Jolly good!

This diagram will adjust its theme based on light/dark theme. You can find more features from the Mermaid website.