One Month with the Zhi Theme: Mermaid v11 Upgrade Experience

One Month In

It’s been nearly a month since the previous article Switched My Blog Theme: From Hugo NexT to Self-Written Zhi. During this month, the theme has been running stably without major issues. Replacing the NexT theme was the right decision — although there was some initial adjustment, the experience is now significantly better.

After a month of use, the theme’s stability has exceeded expectations. My initial concerns — whether pure Hugo Pipes without build tools could support complex requirements — were proven unfounded. Daily maintenance has become very simple; modifying a feature no longer requires digging through deeply nested SCSS files — one CSS file gets the job done.

But to be honest, the month wasn’t entirely smooth sailing. The issues I encountered centered around a few areas, the most prominent being the Mermaid experience.

Why Upgrade to v11

After writing three or four articles with the Zhi theme, I noticed Mermaid v10’s limitations becoming increasingly apparent. The issues centered on a few things:

Too few basic shapes. v10 only offers [rect], {diamond}, (rounded), [(cylinder)], ((circle)) — a limited set that falls short when drawing even slightly complex architecture diagrams. Want to draw a document icon, hexagon, or trapezoid? You’d either use text as a substitute or write complex code to simulate it.

Weak style control. v10 has almost no style customization capability — nodes could only be differentiated through text content, and basic styling like colors, borders, and font sizes required manual CSS. Mermaid diagrams in dark mode always looked slightly off.

New chart types not supported. v11 introduces many new chart types like architecture and kanban, which simply don’t exist in v10. For a technical blog, these new chart types are highly practical.

Performance issues. v10’s initialization was outdated, using blocking load approaches like mermaid.initialize({startOnLoad:true}), causing noticeable lag during page load.

Considering all these factors, I decided to upgrade to Mermaid v11.

Technical Changes

main.js Rewrite

The core of the upgrade was rewriting the initMermaid() function in main.js. The original v10 code was simple:

javascript
1
mermaid.initialize({startOnLoad: true});

v11 changed to asynchronous async/await loading:

javascript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
async function initMermaid() {
    var hasMermaidCode = document.querySelector('code.language-mermaid, pre.mermaid');
    if (!hasMermaidCode || !window.mermaid) return;

    var isDark = document.querySelector('[data-theme="dark"]');
    await window.mermaid.initialize({
        startOnLoad: false,
        securityLevel: 'loose',
        theme: 'base',
        themeVariables: isDark ? darkThemeVars : lightThemeVars
    });

    // Process code blocks, replace with pre tags
    document.querySelectorAll('code.language-mermaid').forEach(function(block) {
        var pre = document.createElement('pre');
        pre.className = 'mermaid';
        pre.textContent = block.textContent;
        var wrapper = block.closest('.code-block-wrapper');
        if (wrapper) { wrapper.replaceWith(pre); }
        else { block.replaceWith(pre); }
    });

    await window.mermaid.run();
}

Key changes:

  1. Synchronous initialization changed to async async/await
  2. Mermaid only loads and initializes when a Mermaid code block is detected
  3. Supports dynamic switching of themeVariables for dark/light themes
  4. Theme setting changed from default to base with custom themeVariables

CDN Changes

The CDN link in the mermaid.html template also changed from pinned version to versionless:

html
1
2
3
4
5
<!-- v10 version pinned -->
<script src="https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js"></script>

<!-- v11 versionless -->
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>

This ensures the latest version is always used, getting new features and bug fixes promptly.

v11 vs v10 Feature Comparison

Node Shape Expansion

v10 basic shapes:

  • [rect] Rectangle
  • {diamond} Diamond
  • (rounded) Rounded rectangle
  • [(cylinder)] Cylinder
  • ((circle)) Circle

v11 extended shapes:

  • @{ shape: doc } Document icon
  • @{ shape: cyl } Cylinder
  • @{ shape: diam } Diamond
  • @{ shape: hex } Hexagon
  • @{ shape: stadium } Stadium
  • @{ shape: rounded } Rounded rectangle
  • @{ shape: trapezoid } Trapezoid
  • @{ shape: double-circle } Double circle
  • @{ shape: circle } Circle

Style Control

v10 had almost no style control, only differentiating nodes through text content.

v11 introduced classDef and class:

yaml
1
2
3
classDef primary fill:#e1f5fe,stroke:#0288d1
classDef warn fill:#fff3e0,stroke:#ef6c00
classDef storage fill:#e8f5e9,stroke:#4caf50

Then assign styles to nodes:

mermaid
graph TD
    A@{ shape: doc, label: "Document" } --> B@{ shape: diam, label: "Decision" }
    B -->|Yes| C@{ shape: hex, label: "Process" }
    B -->|No| D@{ shape: cyl, label: "Database" }
    
    class A,C primary
    class B warn
    class D storage

New Chart Types

v11 new additions:

  • architecture (v11.1+) - Architecture diagram, specifically for system architecture design
  • kanban (v11.0+) - Kanban board, suitable for project management display
  • timeline improvements - Better timeline style control
  • gitgraph - Git branch diagram enhancements

Layout Engine

v11 supports the ELK layout engine, providing better automatic layout for complex diagrams:

yaml
1
2
3
4
5
6
7
%%{init: {'theme': 'base', 'themeVariables': {}}}%%

graph TD
    A@{ shape: doc, label: "Frontend App" } --> B@{ shape: diam, label: "Load Balancer" }
    B --> C@{ shape: cyl, label: "App Server" }
    C --> D@{ shape: cyl, label: "Database" }
    C --> E@{ shape: cyl, label: "Cache" }

Sequence Diagram Enhancements

v11 supports rect backgrounds, which weren’t available in v10:

mermaid
sequenceDiagram
    participant C as Client
    participant S as Server
    
    rect rgba(76,175,80,0.1)
        Note over C,S: Authentication Process
        C->>S: login(username, password)
        S->>S: Validate user info
        S->>C: auth_token
    end
    
    Note over C: Use token
    C->>S: api_call(auth_token)

Theme Variable Customization

v11 provides comprehensive style control via themeVariables:

javascript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
var lightThemeVars = {
    background: '#FAFAFA',
    primaryColor: '#EDE9F6',
    primaryBorderColor: '#D5CFF0',
    primaryTextColor: '#1A1A2E',
    // ... more variables
};

var darkThemeVars = {
    background: '#1e1e2e',
    primaryColor: '#313244',
    primaryBorderColor: '#45475a',
    primaryTextColor: '#cdd6f4',
    // ... more variables
};

Practical Before and After

v10 Style Diagram

mermaid
graph LR
    A[User Request] --> B{Nginx}
    B -->|Static Assets| C[CDN]
    B -->|API Call| D[Go Service]
    D --> E[(PostgreSQL)]
    D --> F[(Redis)]
    C --> G[User Browser]

Issues: monotonous shapes, bland styling, lack of depth.

v11 Style Diagram

mermaid
graph TD
    subgraph Collect[Collection Layer]
        A1@{ shape: doc, label: "Prometheus Agent 1" }
        A2@{ shape: doc, label: "Prometheus Agent 2" }
    end

    subgraph VMAgent[vmagent Cluster]
        B1@{ shape: hex, label: "vmagent-0" }
        B2@{ shape: hex, label: "vmagent-1" }
    end

    subgraph Storage[Storage Layer]
        D1@{ shape: cyl, label: "vmstorage-0" }
        D2@{ shape: cyl, label: "vmstorage-1" }
    end

    A1 --> B1
    A2 --> B2
    B1 --> D1
    B2 --> D2

    classDef storage fill:#e8f5e9,stroke:#4caf50
    classDef compute fill:#e3f2fd,stroke:#2196f3
    class D1,D2 storage
    class B1,B2 compute

Advantages: rich shapes, layered styling, clear structure, great visual effect.

Theme Integration

When switching between dark and light modes, v11’s re-rendering mechanism is much better than v10. In v10, Mermaid diagrams wouldn’t automatically update after theme switch — you had to refresh the page.

v11’s implementation is clever:

  1. On theme switch, add a re-rendering class to all Mermaid containers
  2. After 200ms, reinitialize Mermaid with the new themeVariables
  3. Clear the data-processed attribute on containers
  4. Re-inject diagram content
  5. Execute mermaid.run() to render diagrams in the new theme
  6. Remove the re-rendering class

This mechanism ensures smooth transition of diagrams when switching themes.

Upgrade Process

The actual upgrade process was simpler than expected. Two files were modified:

  1. mermaid.html - CDN link updated
  2. main.js - initMermaid() function rewritten

The code changes weren’t large, but debugging took some time. The main issues were:

  • async/await error handling needed refinement
  • Dark mode color schemes for theme variables needed repeated adjustments
  • Re-rendering delay timing needed testing to determine

The entire upgrade process took about half a day, mostly spent on debugging and style optimization.

Release and Deployment

This upgrade was released with Zhi theme version v0.1.0. The GitHub Actions CI/CD workflow automatically triggers when a tag is pushed:

yaml
1
2
3
4
5
name: Release
on:
  push:
    tags:
      - 'v*'

Build, test, package, and release in one pipeline. First time using GitHub Releases — the experience was better than expected.

The Role of AI

During this upgrade, AI played a significant role, mainly:

  1. API documentation queries - Looking up Mermaid v11’s official docs to understand new features
  2. Code generation - Rewriting the initMermaid() function based on v11 API
  3. Debugging assistance - Helping troubleshoot async/await async loading issues
  4. Style optimization - Providing color scheme suggestions for themeVariables

Particularly worth mentioning is the re-rendering logic during theme switching — AI’s suggestions were very valuable. The first attempt at calling mermaid.initialize() directly caused memory leaks; the solution AI provided was to achieve correct re-rendering by clearing the data-processed attribute.

Summary

Upgrading from Mermaid v10 to v11 was well worth it. The new features genuinely improve the diagram experience, especially:

Shape expansion makes diagrams more vivid, no longer limited to basic shapes Style control gives diagrams depth and improves the professionalism of technical documentation New chart types expand usage scenarios Async loading improves page performance Theme adaptation makes dark mode experience seamless

Although the upgrade process involved some technical details to handle, overall it was a successful experience. The Zhi theme’s Mermaid v11 support is now quite comprehensive, meeting most technical blog diagramming needs.

There are other areas that could be upgraded, like newer MathJax versions or better code highlighting styles. But those can wait for the next iteration. The current state is stable enough — let’s keep using it as is for now.