This comprehensive guide covers setup, implementation, and troubleshooting of Mermaid diagrams in Jekyll sites. Mermaid allows you to create diagrams and visualizations using simple text syntax.

Table of Contents

  1. Overview
  2. Installation & Setup
  3. Configuration
  4. Usage Examples
  5. Troubleshooting
  6. Performance Optimization
  7. References & Credits

Overview

Mermaid is a JavaScript-based diagramming and charting tool that renders Markdown-inspired text definitions to create and modify diagrams dynamically. It supports:

  • Flowcharts
  • Sequence diagrams
  • Class diagrams
  • State diagrams
  • Entity relationship diagrams
  • User journey diagrams
  • Gantt charts
  • Pie charts
  • Git graphs
  • And more…

Why This Implementation?

Our Jekyll site uses a hybrid approach combining:

  • jekyll-mermaid plugin for build-time processing
  • Runtime JavaScript conversion for fenced code blocks
  • CDN delivery for performance and reliability

This ensures compatibility across different content authoring methods while maintaining optimal performance.

Installation & Setup

1. Gemfile Configuration

Add the jekyll-mermaid plugin to your Gemfile:

# In docs/Gemfile group :jekyll_plugins do gem 'jekyll-mermaid', '~> 1.0.0' # ... other plugins end

2. Jekyll Configuration

Configure Mermaid in your _config.yml:

# Enable mermaid diagrams mermaid: src: https://cdn.jsdelivr.net/npm/mermaid@11.9.0/dist/mermaid.min.js plugins: - jekyll-mermaid # ... other plugins

3. Layout Integration

Add Mermaid support to your layouts. For universal support, add to _layouts/default.html:

<!-- Mermaid support: convert fenced code blocks (```mermaid) and initialize --> <script src="https://cdn.jsdelivr.net/npm/mermaid@11.9.0/dist/mermaid.min.js"></script> <script> (function () { function convertMermaidCodeFences() { try { var codeBlocks = document.querySelectorAll("pre > code.language-mermaid, pre > code.mermaid"); codeBlocks.forEach(function (code) { var pre = code.parentElement; var container = pre.parentElement; var div = document.createElement("div"); div.className = "mermaid"; div.textContent = code.textContent; // preserve raw diagram text container.replaceChild(div, pre); }); } catch (e) { console.warn("Mermaid code fence conversion failed:", e); } } function initMermaidNow() { try { if (!window.mermaid) return false; convertMermaidCodeFences(); if (typeof mermaid.initialize === "function") { mermaid.initialize({ startOnLoad: true }); } if (typeof mermaid.run === "function") { mermaid.run({ querySelector: ".mermaid" }); } else if (typeof mermaid.init === "function") { mermaid.init(undefined, document.querySelectorAll(".mermaid")); } return true; } catch (e) { console.error("Mermaid initialization error:", e); return false; } } function whenReady(fn) { if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", fn); } else { fn(); } } whenReady(function () { if (initMermaidNow()) return; var attempts = 0; var timer = setInterval(function () { attempts++; if (initMermaidNow() || attempts > 50) { clearInterval(timer); } }, 100); }); })(); </script>

4. Install Dependencies

cd docs bundle install

Configuration

Basic Configuration Options

In _config.yml, you can customize Mermaid settings:

mermaid: src: https://cdn.jsdelivr.net/npm/mermaid@11.9.0/dist/mermaid.min.js # Optional: Custom configuration config: theme: default startOnLoad: true flowchart: htmlLabels: true curve: basis sequence: diagramMarginX: 50 diagramMarginY: 10 actorMargin: 50 width: 150 height: 65 boxMargin: 10 boxTextMargin: 5 noteMargin: 10 messageMargin: 35

Advanced Layout-Specific Configuration

For specialized layouts (e.g., presentation slides), you can create custom configurations:

<!-- In _layouts/delivery-slides.html --> <script> mermaid.initialize({ theme: "dark", startOnLoad: true, flowchart: { htmlLabels: true, curve: "linear", }, }); </script>

Usage Examples

This is the preferred method as it’s compatible with most Markdown processors and avoids build-time HTML wrapping issues:

```mermaid graph TD A[Start] --> B{Is it?} B -->|Yes| C[OK] B -->|No| D[End] ```

Method 2: Jekyll Liquid Tags

Note: This method can cause issues with <p> tag wrapping. Use fenced code blocks when possible.

<script src="https://cdn.jsdelivr.net/npm/mermaid@11.9.0/dist/mermaid.min.js"></script><div class="mermaid"> sequenceDiagram participant A as Alice participant B as Bob A->>B: Hello Bob, how are you? B-->>A: Great! </div>

Example Diagram Types

Flowchart

```mermaid graph LR A[Square Rect] --> B((Circle)) A --> C(Round Rect) B --> D{Rhombus} C --> D ```

Sequence Diagram

```mermaid sequenceDiagram participant A as Client participant B as Server A->>B: Request B-->>A: Response ```

Class Diagram

```mermaid classDiagram class Animal { +String name +int age +makeSound() } class Dog { +String breed +bark() } Animal <|-- Dog ```

Troubleshooting

Common Issues and Solutions

1. Diagrams Render as Code Blocks

Symptoms: Mermaid syntax appears as plain text in <pre><code> blocks instead of rendered diagrams.

Causes:

  • Missing JavaScript initialization
  • Script loading after content render
  • Incorrect layout configuration

Solutions:

// Check if Mermaid loaded console.log("Mermaid loaded:", typeof window.mermaid !== "undefined"); // Manually trigger conversion if (window.mermaid) { mermaid.run(); }

2. “Syntax Error” Messages in Diagrams

Symptoms: Diagram container shows “Syntax error in graph” or similar error text.

Causes:

  • HTML entities in diagram text (e.g., &gt; instead of >)
  • Jekyll Liquid processing interference
  • Invalid Mermaid syntax

Solutions:

  • Use fenced code blocks instead of Liquid tags
  • Verify diagram syntax at Mermaid Live Editor
  • Check for HTML entity encoding in source

3. Mixed Content Warnings

Symptoms: Browser console shows mixed content warnings when loading Mermaid from CDN on HTTPS sites.

Solutions:

# In _config.yml - ensure HTTPS CDN URL mermaid: src: https://cdn.jsdelivr.net/npm/mermaid@11.9.0/dist/mermaid.min.js

4. Script Loading Race Conditions

Symptoms: Intermittent rendering failures, especially on slower connections.

Solutions:

// Improved initialization with polling function initMermaidWithRetry() { var attempts = 0; var maxAttempts = 50; function tryInit() { if (window.mermaid && document.readyState === "complete") { mermaid.run(); return true; } attempts++; if (attempts < maxAttempts) { setTimeout(tryInit, 100); } else { console.warn("Mermaid initialization timeout"); } return false; } tryInit(); }

Debugging Tools

Browser Console Debugging

// Check Mermaid availability console.log("Mermaid version:", mermaid?.version); // List all mermaid elements console.log("Mermaid elements:", document.querySelectorAll(".mermaid")); // Test diagram parsing try { mermaid.parse("graph TD; A-->B"); console.log("Mermaid syntax valid"); } catch (e) { console.error("Mermaid syntax error:", e); }

E2E Testing Validation

Use Playwright tests to ensure reliable rendering:

// Example test validation test("Mermaid diagram renders correctly", async ({ page }) => { await page.goto("/docs/mermaid-example/"); // Wait for Mermaid to load and render await page.waitForSelector(".mermaid svg", { timeout: 8000 }); // Verify no syntax errors const errorCount = await page.locator('.mermaid:has-text("Syntax error")').count(); expect(errorCount).toBe(0); // Verify SVG content const svgCount = await page.locator(".mermaid svg").count(); expect(svgCount).toBeGreaterThan(0); });

Performance Optimization

CDN Configuration

Use a reliable CDN with proper versioning:

# Recommended CDN sources (choose one) mermaid: # jsDelivr (recommended) src: https://cdn.jsdelivr.net/npm/mermaid@11.9.0/dist/mermaid.min.js # Alternative: unpkg # src: https://unpkg.com/mermaid@11.9.0/dist/mermaid.min.js # Alternative: cdnjs # src: https://cdnjs.cloudflare.com/ajax/libs/mermaid/11.9.0/mermaid.min.js

Lazy Loading

For pages with many diagrams, consider lazy loading:

// Intersection Observer for lazy loading const observer = new IntersectionObserver((entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { const element = entry.target; if (!element.dataset.rendered) { mermaid.render("mermaid-" + Date.now(), element.textContent).then((result) => { element.innerHTML = result.svg; element.dataset.rendered = "true"; }); } } }); }); document.querySelectorAll(".mermaid").forEach((el) => observer.observe(el));

Bundle Size Optimization

Consider self-hosting for production:

# Download and serve locally npm install mermaid cp node_modules/mermaid/dist/mermaid.min.js assets/js/

References & Credits

Internal Documentation

  • Mermaid Quick Start: Quick Setup Guide - Rapid setup and basic usage patterns for immediate productivity
  • Mermaid Diagrams Sample: Mermaid Diagrams Showcase - Live examples of all supported diagram types
  • Mermaid Examples: Comprehensive Mermaid Examples - Extended collection of real-world diagram patterns and use cases
  • Quick Start Guide: Getting Started - Rapid setup guide for the complete development environment
  • Testing Documentation: See our comprehensive E2E testing setup for Mermaid diagram validation

Official Documentation

Jekyll Integration

CDN Providers

Testing & Validation

Community Resources

MIJUG .NET Workspace Integration

  • Performance Optimization: This implementation follows our workspace’s performance targets (< 12s builds, < 90s test suite)
  • Accessibility Standards: WCAG 2.1 AA compliance enforced via automated testing
  • Multi-Browser Support: Validated across Chromium, Firefox, and WebKit using our specialized test runner
  • Conditional Loading: Optimized script loading only when use_mermaid: true is set in page front matter
  • Development Workflow: Integrated with FrontMatter CMS and Jekyll drafts workflow for streamlined content creation

Contributing

This implementation was developed for the MIJUG .NET workspace and incorporates best practices from:

  • Mermaid.js community for syntax and rendering guidance
  • Jekyll community for plugin integration patterns
  • Playwright team for E2E testing methodologies
  • jsDelivr team for CDN reliability recommendations

Version History

  • v1.0 (2025-08-08): Initial implementation with hybrid approach
  • v1.1 (2025-08-08): Added runtime fenced code block conversion
  • v1.2 (2025-08-08): Enhanced error handling and debugging tools

License Acknowledgments

  • Mermaid.js: MIT License - Copyright (c) 2014 - 2024 Knut Sveidqvist
  • jekyll-mermaid: MIT License - Copyright (c) 2015 Jason Bellamy
  • Jekyll: MIT License - Copyright (c) 2008-2015 Tom Preston-Werner

For the most current information, always refer to the official documentation links provided above.