Mermaid Hybrid Stack Integration Guide
CompleteThe Problem
Technical documentation suffers from a tooling fragmentation problem. Flowcharts need one tool, data visualizations need another, and architecture diagrams with nested containers need a third. Most teams either force everything into a single tool (producing mediocre output for half their diagram types) or use visual editors like Figma and Lucidchart that create version control headaches when diagrams drift from the code they document.
Mermaid has emerged as the standard for text-based diagrams: it renders natively on GitHub, version-controls as plain text, and has broad ecosystem support. But Mermaid alone cannot produce publication-quality heatmaps, grouped bar charts, or multi-layer architecture diagrams with spatial containment. Vega-Lite handles data visualization with a declarative grammar that Mermaid lacks. D2 handles nested architecture layouts with a spatial positioning engine that Mermaid’s sequential flow model cannot replicate.
The Python ecosystem (Matplotlib, ReportLab) offers alternatives, but introduces its own problems: system library dependencies that break across Python versions, Chromium/Puppeteer installation complexity on WSL 2 and containerized environments, and rendering failures that produce no error messages. Installing Mermaid CLI natively requires tracking 15+ system packages across different Linux distributions.
No integrated pipeline existed for combining these three tools with version control, automated rendering, CI validation, and both PDF and HTML output. This project was built to create that pipeline, with every tool free and open-source.
What Was Built
A 14-phase implementation guide for building an enterprise-grade diagram-as-code pipeline that combines three specialized tools into a unified rendering system. Each tool handles the diagram types it does best:
- Mermaid (.mmd files): Flowcharts, sequence diagrams, Gantt charts, class diagrams, and state diagrams. Best-in-class for developer-familiar syntax and GitHub-native rendering.
- Vega-Lite (.vl.json files): Heatmaps, grouped bar charts, scatter plots, and data-driven visualizations. Declarative JSON grammar produces publication-quality output from structured data.
- D2 (.d2 files): Multi-layer architecture diagrams with nested containers, spatial positioning, and connection routing. The ELK layout engine produces the cleanest spatial layouts for system architecture.
The guide includes 37 automation scripts covering installation, configuration, rendering, validation, and batch processing. 10 multi-tool diagrams demonstrate the full range of capabilities across all three tools. A 7-exercise interactive tutorial takes beginners from their first flowchart to a complete rendering pipeline.
All tools are free and open-source: Mermaid (MIT), Vega-Lite (BSD-3-Clause), D2 (MPL-2.0). Total infrastructure cost: $0. The Docker-first rendering approach eliminates 15+ system library dependencies by containerizing Chromium and Puppeteer inside the Mermaid CLI Docker image.
Tool Selection
The three-tool approach is not a compromise. Each tool was selected because it is the best available option for its diagram category. The decision matrix below maps diagram types to tool suitability based on rendering quality, syntax complexity, and output format support.
| Criterion | Mermaid | Vega-Lite | D2 |
|---|---|---|---|
| Syntax | Markdown-like DSL | Declarative JSON | HCL-like DSL |
| Rendering | Chromium (Docker) | Canvas/SVG (Node.js) | Playwright/ELK |
| GitHub support | Native in markdown | Pre-render to SVG | Pre-render to SVG |
| Layout engine | Dagre (sequential) | Grammar of Graphics | ELK (spatial, free) |
| License | MIT | BSD-3-Clause | MPL-2.0 |
| Cost | $0 | $0 | $0 (ELK free, TALA $240/yr) |
The ELK layout engine for D2 was chosen over TALA specifically because it is free. TALA produces marginally better layouts for very complex diagrams, but at $240/year it violates the zero-cost constraint. ELK handles the complexity level required for this project without compromise.
Architecture
The rendering infrastructure uses a Docker-first approach. Rather than installing Chromium, Puppeteer, and 15+ system libraries directly on the host, the Mermaid CLI runs inside the minlag/mermaid-cli Docker image (~400 MB, one-time download).
The Docker wrapper scripts map the host user ID into the container (--user $(id -u):$(id -g)) so rendered files are owned by the developer, not root. Enterprise theme configuration files (light and dark variants) standardize the visual output: Inter/Segoe UI fonts at 14px, 60px rank spacing, HTML labels enabled, and basis curve interpolation for flowchart edges.
The PostToolUse hook closes the development loop. When any .mmd, .vl.json, or .d2 file is written, the hook automatically validates the syntax (catching errors in 1-2ms via @probelabs/maid) and triggers a render. This eliminates manual render cycles during iterative diagram development. The hook uses POSIX-compatible syntax (explicit bash -c, case/esac, exported PATH) to avoid shell compatibility issues in Claude Code’s constrained hook environment.
Enterprise Theme System
Two configuration files standardize all Mermaid output:
Light theme (config.json): Primary color #F0F4FC, text color #1F2329, border color #2C5F8A. Inter/Segoe UI/Roboto font stack at 14px with HTML labels enabled. Flowcharts use basis curve interpolation with 60px rank spacing and 40px node spacing for clean, readable layouts.
Dark theme (config-dark.json): Inverted palette with #1E293B primary, light text, and muted borders. Produces -dark suffixed output files alongside the light variants. Both themes share the same layout parameters, so switching themes does not change diagram geometry.
The theme files are passed to the Docker wrapper via the -C flag, ensuring every render uses consistent styling regardless of who runs the command or which machine it runs on. This eliminates the “it looks different on my machine” problem that plagues visual diagramming tools.
Version Control Strategy
Diagram source files (.mmd, .vl.json, .d2) are the source of truth and always committed to git. Rendered outputs (.svg, .png, .pdf) are git-ignored via the global .gitignore_global configuration. This keeps diffs meaningful: reviewers see the text change that modified the diagram, not a binary artifact diff.
For GitHub README rendering, Mermaid blocks render natively in markdown without any committed artifacts. For portfolio sites and PDF documents, the CI pipeline pre-renders to SVG/PNG and references the output files directly.
Implementation Phases
The guide is structured as 14 phases, grouped into six functional areas. Each phase includes a README with step-by-step instructions, automation scripts, and validation checks.
| Phase | Name | Time | Key Deliverable |
|---|---|---|---|
| 0 | Docker Setup | 10 min | Docker Desktop WSL 2 backend verified |
| 1 | Mermaid CLI | 15 min | mermaid-render wrapper script |
| 2 | Enterprise Theme | 10 min | Light + dark theme config files |
| 3 | Battle Test | 20 min | Complex diagram stress test |
| 4 | Syntax Validation | 5 min | mermaid-validate wrapper (1-2ms) |
| 5 | Claude Skill | 15 min | AI-assisted diagram generation skill |
| 6 | Auto-Render Hook | 10 min | PostToolUse hook for automatic SVG output |
| 7 | GitHub Rendering | 10 min | Native Mermaid blocks + .gitignore setup |
| 8 | PDF Pipeline | 20 min | render-all-diagrams + mermaid-pdf scripts |
| 9 | HTML Embedding | 10 min | Astro/static site embed templates |
| 10 | Vega-Lite | 15 min | vegalite-render wrapper for data charts |
| 11 | D2 Diagrams | 15 min | d2-render wrapper with ELK layout |
| 12 | MCP Evaluation | 5 min | Evaluated and rejected MCP server approach |
| 13 | Validation | 30 min | Full pipeline end-to-end verification |
Phase groupings: Docker foundation (Phases 0-1), Mermaid mastery (Phases 2-4), AI integration (Phases 5-6), output pipelines (Phases 7-9), extended tools (Phases 10-11), and evaluation and validation (Phases 12-13).
Total estimated time: approximately 3 hours. The Docker foundation phases take 25 minutes and provide the base for everything that follows.
Rendering Pipeline
Seven custom wrapper scripts standardize the rendering workflow across all three tools:
- mermaid-render: Docker-based SVG/PNG rendering with enterprise light theme. Mounts the current directory, maps user permissions, applies
config.jsontheme, and outputs to the same directory as the source file. - mermaid-render-dark: Same as above but uses
config-dark.jsonfor dark theme output. Produces-darksuffixed files alongside the light variants. - mermaid-validate: Runs @probelabs/maid syntax validation in 1-2ms without starting Chromium. Catches the most common errors (unquoted labels, literal
\ninstead of<br/>, incorrect pipe label syntax) before the expensive render step. - vegalite-render: Converts Vega-Lite JSON specifications to SVG and PNG via the
vl2svgandvl2pngNode.js tools. Requires thecanvasnpm package for PNG output. - d2-render: Renders D2 architecture diagrams using the ELK layout engine. Requires Playwright and
libasound2t64for PNG rendering on Ubuntu. - render-all-diagrams: Batch script that walks
~/projects/*/diagrams/directories and renders every source file using the appropriate tool based on file extension. - mermaid-pdf: Converts Markdown documents with embedded Mermaid to PDF via Pandoc, pre-rendering Mermaid blocks as 3x-scale PNGs (~300 DPI) for print-quality output.
The rendering pipeline processes 10 diagrams across Mermaid, Vega-Lite, D2, and Markdown:
| # | Diagram | Tool | Source File | Purpose |
|---|---|---|---|---|
| 1 | System Architecture | D2 | system-architecture.d2 | 4-layer nested container layout |
| 2 | Threshold Escalation | Mermaid | threshold-escalation.mmd | Complexity scoring flowchart |
| 3 | Token Economics | Vega-Lite | token-economics.vl.json | Cost comparison grouped bars |
| 4 | Before/After Workflow | Mermaid | before-after-workflow.mmd | Manual vs orchestrated process |
| 5 | Config File Hierarchy | Mermaid | config-hierarchy.mmd | Precedence arrow diagram |
| 6 | Phase Dependencies | Mermaid | phase-dependencies.mmd | Critical path visualization |
| 7 | Decision Matrix | Vega-Lite | decision-matrix.vl.json | Workload-to-pattern heatmap |
| 8 | Gantt Timeline | Mermaid | gantt-timeline.mmd | 14-17 hour implementation schedule |
| 9 | Error Resolution | Mermaid | error-resolution.mmd | Common failure patterns with fixes |
| 10 | Component Inventory | Markdown | inventory-table.md | Skills, agents, plugins, hooks table |
Each diagram demonstrates a specific tool capability. The D2 architecture diagram showcases nested container layouts that Mermaid cannot produce. The Vega-Lite heatmap encodes 60 data points (10 workload types across 6 orchestration patterns) into a color-coded grid that would require a manual HTML table in any other tool. The Mermaid Gantt chart provides native timeline visualization with date parsing and task dependency rendering.
AI-Assisted Generation
Phase 5 creates a Claude Code skill that generates syntactically valid Mermaid diagrams from natural language descriptions. The skill encodes the most common syntax rules as guardrails:
- Node labels must always be quoted:
A["Label"], neverA[Label] - Edge labels in pipes are never quoted:
-->|Label|, never-->|"Label"| - Line breaks use
<br/>withhtmlLabels: true, never literal\n - Flowchart direction is declared once:
flowchart TDorflowchart LR
Phase 6 adds a PostToolUse hook that triggers automatically when Claude writes any diagram source file. The hook detects the file extension and routes to the correct tool:
*.mmd → maid validate + mermaid-render
*.vl.json → vegalite-render
*.d2 → d2-render
The hook uses POSIX-compatible syntax to avoid shell compatibility issues. Early versions used [[ ]] test syntax, which failed because Claude Code’s hook runner uses a minimal shell, not bash. The fix was wrapping the entire hook in explicit bash -c '...' with case/esac for pattern matching and export PATH="$HOME/bin:$PATH" to ensure wrapper scripts are discoverable.
This combination eliminates the write-save-switch-render-check cycle. The developer describes a diagram, Claude generates the source file, the hook validates and renders it, and the SVG appears in the workspace. Iteration time drops from minutes to seconds.
Skill Guardrails in Practice
The Claude Code skill encodes the four most common Mermaid syntax errors as explicit rules:
| Rule | Incorrect | Correct |
|---|---|---|
| Node labels | A[Label] | A["Label"] |
| Edge labels | `—> | “Label” |
| Line breaks | \n | <br/> |
| Direction | Implicit | flowchart TD |
These four rules alone prevent approximately 80% of the syntax errors encountered during the guide’s development. The skill also enforces the enterprise theme configuration, ensuring that AI-generated diagrams match the project’s visual standards without manual correction.
Tutorial System
The Dogs and Cats tutorial provides 7 hands-on exercises that progressively introduce the full diagram pipeline. Each exercise uses pet-themed examples to make abstract concepts tangible.
| Exercise | Title | Concept |
|---|---|---|
| 1 | Hello Diagrams | First flowchart + render to SVG |
| 2 | Theme Your Kennel | Light and dark enterprise themes |
| 3 | Validate the Litter | Syntax errors, debugging, and maid validation |
| 4 | Teach Claude to Draw | AI skill + PostToolUse hook integration |
| 5 | Publish to GitHub | Version control + GitHub native rendering |
| 6 | Data Charts and Blueprints | Vega-Lite data charts + D2 architecture |
| 7 | Full Pipeline Test | End-to-end render, validate, and export |
The tutorial includes a starter project at tutorial/assets/sample-project/ with five files: a Mermaid flowchart (light and dark variants), a Vega-Lite bar chart for adoption statistics, a D2 architecture diagram for the shelter’s system layout, and a README.
Each exercise takes 15-25 minutes. The full tutorial requires approximately 2-3 hours and assumes no prior experience with any of the three tools. The progression is designed so that each exercise builds on the skills from the previous one, but individual exercises can be completed independently.
The tutorial builds from single-tool basics to multi-tool orchestration. Exercises 1-3 cover Mermaid exclusively (render, theme, validate). Exercise 4 introduces AI assistance. Exercise 5 covers version control and GitHub publishing. Exercise 6 expands to Vega-Lite and D2. Exercise 7 validates the complete pipeline end-to-end. By the final exercise, the developer has working wrapper scripts for all three tools, an active PostToolUse hook, and a validated rendering pipeline.
Debugging Log
Implementation surfaced 11 real errors, each documented with exact symptoms, root causes, and verified fixes. These are not hypothetical scenarios. Every error was encountered during the actual build process.
| Error | Symptom | Fix |
|---|---|---|
| Docker EACCES | Permission denied writing output files | Add --user $(id -u):$(id -g) flag to Docker run |
Literal \n in labels | \n renders as text instead of line break | Use <br/> with htmlLabels: true in config |
| npm EACCES | Global install fails without sudo | Use sudo npm install -g for CLI tools |
| maid rejects pipes | Quoted labels inside pipe syntax fail | Remove quotes from edge labels: `—> |
| Skill not detected | Claude Code cannot find the skill file | Create directory with SKILL.md inside, not standalone file |
| Hook PATH failure | Hook fires but wrapper script not found | Add export PATH="$HOME/bin:$PATH" in hook body |
| Shell compatibility | [[ ]] syntax fails in hook runner | Use POSIX case/esac wrapped in bash -c |
| Vega-Lite PNG blank | Canvas package missing for PNG output | Install canvas npm package globally |
| D2 Playwright deps | Missing system library for PNG rendering | Install libasound2t64 on Ubuntu |
| MCP server not found | mermaid-mcp npm package does not exist | Rejected MCP approach, use skill + hook instead |
| Batch render stalls | Sequential Docker renders exhaust resources | Increase timeout to 60-90s, batch with delays |
Phase 12 (MCP Evaluation) deserves special mention. The Mermaid MCP server was evaluated as a potential alternative to the skill + hook approach. After testing, it was rejected: the MCP server package did not exist in the npm registry, and the skill + hook combination already provided the same automated rendering workflow with better error handling and no additional dependencies. The decision to reject was documented as a finding, not swept under the rug.
Outcome
The completed pipeline delivers enterprise-quality diagram output from version-controlled source files:
- 37 automation scripts covering installation, configuration, rendering, validation, and batch processing across all three tools
- 10 diagrams across Mermaid (6), Vega-Lite (2), D2 (1), and Markdown (1), demonstrating the full range of the hybrid stack
- 7 tutorial exercises with a starter project, progressive difficulty, and standalone completability
- 11 documented real errors with root cause analysis and verified fixes
- Zero infrastructure cost: all tools are MIT, BSD-3, or MPL-2.0 licensed
The pipeline produces three output formats: SVG for web embedding with infinite resolution scaling, PNG at 3x scale (~300 DPI) for print-quality PDF documents, and native Mermaid blocks for GitHub README rendering without image file overhead.
This rendering infrastructure powers all 10 diagrams in the companion orchestration guide, including the system architecture diagram (D2), token economics comparison (Vega-Lite), and threshold escalation flowchart (Mermaid). The pipeline also generated the diagrams for the portfolio runbook PDFs.
Output Quality Benchmarks
SVG outputs use the enterprise theme configuration with Inter/Segoe UI font stack, 14px base font size, and 60px minimum rank spacing. These settings produce diagrams that are legible at both screen resolution and 300 DPI print resolution without manual adjustment. PNG outputs at 3x scale produce images at approximately 2340x1650 pixels for a standard landscape diagram, suitable for inclusion in PDF documents, slide decks, and print materials without upscaling artifacts.
Lessons Learned
-
Docker isolation eliminates dependency tracking. One
docker pullreplaces 15+apt-getpackages. The Mermaid CLI Docker image bundles Chromium, Puppeteer, and all required fonts into a single ~400 MB image that works identically on WSL 2, macOS, and Linux. The time saved on dependency management across environments far outweighs the Docker image download. -
Syntax validation before rendering saves 10x in feedback time. @probelabs/maid validates Mermaid syntax in 1-2ms. A full Chromium render takes 5-10 seconds (longer on Docker cold start). Running validation first catches ~90% of errors at 1/5000th the cost. This is the single highest-leverage optimization in the pipeline.
-
Three-tool specialization beats single-tool compromise. Forcing all diagram types into Mermaid produces mediocre heatmaps and poor architecture layouts. Forcing everything into D2 loses GitHub native rendering and Gantt chart support. The overhead of maintaining three wrapper scripts is trivial compared to the quality improvement from using each tool where it excels.
-
PostToolUse hooks close the development loop. Before the hook, diagram iteration required: write source, save, switch to terminal, run render command, switch to file explorer, open SVG, check output, switch back. After the hook: write source, check output. The hook transforms a 6-step manual process into a 2-step automated one.
-
Document every error at the point of failure. The 11-error debugging log was written as errors occurred, not reconstructed afterward. Root cause analysis is freshest in the moment. Three of the documented errors (hook PATH, shell compatibility, MCP evaluation) would have been impossible to reconstruct accurately after the fact because the symptoms were transient.
-
Reject tools that do not meet the bar. Phase 12’s MCP server evaluation ended in a rejection, and that rejection was documented as a first-class finding. The skill + hook approach provides the same automated rendering workflow with better error handling and no additional dependencies. Recording “we evaluated X and rejected it” prevents future developers from wasting time re-evaluating the same option.
-
Batch rendering needs resource awareness. Sequential Docker renders (each spawning a Chromium instance) can exhaust system resources on constrained environments like WSL 2 with limited memory. The batch render script includes deliberate delays between renders and a 60-90 second timeout per diagram. This was discovered through the “batch render stalls” error and would not have been caught without end-to-end pipeline testing.
Companion Project
This guide works in tandem with the Claude Code Agent Orchestration Guide, which provides the multi-agent coordination system that uses these diagrams.
The orchestration guide’s 10 diagrams were all produced using this rendering pipeline: the system architecture diagram was built in D2 with the ELK layout engine, the token economics comparison was rendered as a Vega-Lite grouped bar chart, and the remaining 6 Mermaid diagrams (threshold flowchart, before/after workflow, config hierarchy, phase dependencies, Gantt timeline, error resolution) used enterprise theme configuration, with the decision matrix rendered as a Vega-Lite chart and the component inventory as a Markdown table.
Together, the two guides demonstrate end-to-end AI-assisted documentation workflows. The orchestration guide structures how AI agents coordinate and review work. This guide structures how that work is visualized, version-controlled, and published. Both share the same Claude Code foundation, automation patterns, and documentation methodology.
GitHub: mermaid-hybrid-stack-guide
Runbook: Mermaid_Hybrid_Stack_Manual_v2.pdf – The 32-page source document covering the full 14-phase pipeline, all three rendering tools, enterprise theme configuration, Docker wrapper architecture, AI-assisted generation, troubleshooting guide with 11 documented errors, and complete reference tables.