
# Claude Code Skills: Optimizing Diagram Generation — SVG vs Mermaid vs Excalidraw Comparison and Design Decisions
This page has been translated by machine translation. View original
Introduction
When writing articles for DevelopersIO, diagrams explaining technical concepts greatly deepen readers' understanding. However, creating diagrams manually every time is tedious.
So I'm using Claude Code's skill feature to build a pipeline that automatically generates diagrams in SVG at article publication time and converts them to PNG. However, the quality of generated diagrams was inconsistent. Thinking "there must be a better way," I actually compared and tested three approaches: SVG (cairosvg), Mermaid CLI, and Excalidraw.
This article shares the comparison results and how I ultimately improved the skill design.
Prerequisites & Environment
- Claude Code
- macOS (Apple Silicon)
- Python 3.14 +
uv(package management) - cairosvg (SVG → PNG conversion)
@mermaid-js/mermaid-cli(Mermaid → PNG conversion)- Playwright (Excalidraw rendering)
Overview of the Three Approaches
The current SVG pipeline operates with the following flow:

I compared this pipeline against other approaches:
| Approach | Mechanism | What Claude writes |
|---|---|---|
| SVG + cairosvg | Claude generates SVG code → PNG conversion with cairosvg | SVG (including coordinates & styles) |
| Mermaid CLI | Claude generates Mermaid notation → PNG conversion with mmdc (Puppeteer) | Mermaid text syntax |
| Excalidraw | Claude generates Excalidraw JSON → PNG conversion via Playwright | Excalidraw JSON (including coordinates) |
Round 1: Simple Workflow Diagram
As the first test, I generated a 3-phase workflow diagram (Plan → Implement → Review) using the same concept across all three approaches.
SVG + cairosvg Result
- Design: Gradient headers, drop shadows, badge icons (H/AI/OK). The most modern-looking
- Japanese: Became tofu (□□□□). Caused by forgetting to specify Hiragino font in
font-family - Layout: Manual coordinate placement, but no problem given this level of simplicity

Mermaid CLI Result
- Design: Standard diagram tool appearance. Node colors can be changed with
classDef, but gradients and shadows are not possible - Japanese: Displayed perfectly. Because Puppeteer renders with a real browser
- Layout: Automatic layout engine handles placement. No manual adjustment needed

Excalidraw Result
- Design: Hand-drawn style lines. Somewhat unsuitable for technical blogs
- Japanese: Displays but rough
- Layout: Text overflows boxes, coordinate misalignment. Has the same "manual coordinate placement" problem as SVG, plus feedback is harder to apply

Round 2: Complex CI/CD Pipeline
I had a question: "Simple diagrams are fine with SVG, but won't arrows break down in complex diagrams?" So I retested with a CI/CD pipeline diagram containing 15 nodes, parallel branching, and feedback loops. Since Excalidraw showed poor layout quality in Round 1, Round 2 was narrowed down to SVG and Mermaid.
SVG + cairosvg
- Parallel branching (3 simultaneous test executions), diamond-shaped decision nodes, dashed feedback loops, rollback paths — all rendered correctly
- No arrow crossings either. Did not break down even with complexity
- With font corrected to Hiragino, Japanese would display without issues as well

Mermaid CLI
- Zero arrow crossings with automatic layout. Stable
- However, OK/NG branch placement can sometimes flow in a counterintuitive direction
- Visually flat, and the quality gap with SVG becomes more noticeable in complex diagrams

Comparison Summary
| Aspect | SVG + cairosvg | Mermaid | Excalidraw |
|---|---|---|---|
| Visual quality | Best (gradients, shadows, badges) | Medium (flat design) | Low (hand-drawn style, text overflow) |
| Japanese support | Resolved by specifying Hiragino font | Supported automatically | Works but rough |
| Layout stability | Manual, but OK if Claude places appropriately | Best (automatic layout) | Manual coordinates + low quality |
| Human workload | Same (Claude instructed via natural language) | Same | Same |
| Visual ceiling | Unlimited (pixel-level control) | Fixed (up to Mermaid theme features) | Fixed to hand-drawn style |
Key Finding: "Writing Cost" Is Irrelevant
Initially I placed importance on "SVG requires 200 lines, Mermaid only 30." But in reality Claude writes the code, so the human cost (describing the diagram in natural language) is the same for all three. Differences in volume of code are not a useful decision criterion.
Conclusion: Continue with SVG + cairosvg
Prioritizing visual quality for public blog diagrams, I adopted the SVG approach. The Japanese tofu problem is a known issue that can be resolved with font specification.
Reflecting in the Skill: What Was Improved
Based on the comparative testing results, I significantly strengthened the SVG guidelines in the skill.
Before Improvement (7 lines of vague instructions)
- Simple, readable design. Minimal decoration
- Color scheme: white background, blue accents, gray supplementary
- Font: Hiragino Sans specified
- Width: within 800px
With just this, Claude would generate diagrams in different styles each session, resulting in inconsistent quality.
After Improvement: 4 Pillars
1. Semantic Color Palette
Colors defined by "purpose":
| Purpose | Main | Sub/Background |
|---|---|---|
| Normal flow | #3B82F6 |
#DBEAFE |
| Success/Complete | #10B981 |
#D1FAE5 |
| Error/NG | #EF4444 |
#FEE2E2 |
| Warning/Decision | #F59E0B |
#FEF3C7 |
By defining colors based on meaning rather than "blue/gray," the design remains consistent across any session.
2. <defs> Template
Providing SVG common parts (shadow filters, arrow markers, gradients) as templates:
<defs>
<filter id="shadow" ...>
<feDropShadow dx="0" dy="2" stdDeviation="3" flood-opacity="0.08"/>
</filter>
<marker id="arrowBlue" ...>
<polygon points="0 0, 8 3, 0 6" fill="#3B82F6"/>
</marker>
<linearGradient id="headerGrad" ...>
<stop offset="0%" stop-color="#3B82F6"/>
<stop offset="100%" stop-color="#1D4ED8"/>
</linearGradient>
</defs>
No longer necessary to think up styles from scratch every time.
3. Design Pattern Definitions
Patterns used repeatedly in diagrams — such as "card-type container," "badge," and "decision node" — are defined with names. No longer necessary to reinvent "rounded card with gradient header" every time.
4. Complexity Limits
Acknowledging SVG's weakness (manual coordinate placement), rules were established to prevent breakdowns:
- 12 nodes or fewer
- 2 or more arrow crossings → split the diagram
- Nesting of 3 or more levels prohibited
Implementation-Level Countermeasures for the Japanese Tofu Problem
The tofu problem discovered in Round 1 tends to be dismissed with "just specify the font and it's fixed," but in the actual skill, 3 layers of defense prevent recurrence.
Layer 1: Root-Level Font Specification (Mandatory Rule)
The following is explicitly stated in the guidelines:
Font: font-family="Hiragino Sans, Hiragino Kaku Gothic ProN, sans-serif" (mandatory)
The key point is setting it on the root <svg> element. Due to CSS inheritance, it applies to all child elements, preventing accidents where font specification is forgotten on individual <text> elements. With sans-serif alone, cairosvg cannot find Japanese glyphs and they become tofu.
Layer 2: Prohibition of Unicode Special Characters
cairosvg also turns symbols not included in the font into tofu. Unicode special characters such as ✓, ✗, and ≥ are prohibited, with alternatives specified:
| NG | Alternative |
|---|---|
✓ |
Draw circle + checkmark shape in SVG |
✗ |
Draw × shape in SVG |
≥ |
ASCII >= |
Even with the font correctly specified, glyphs not included in the font become tofu. This layer covers that blind spot.
Layer 3: Post-Conversion Visual Inspection Loop
As the last line of defense, a rule is established where Claude itself loads the image with the Read tool after PNG conversion and verifies the rendering result:
After conversion, always load the PNG with the Read tool and visually verify the rendering result.
If there are problems, fix the SVG and re-convert, then verify again.
After confirming there are no problems, delete the SVG file and keep only the PNG.
Since Claude is a multimodal LLM, it can detect tofu and overlapping labels by loading the PNG itself. Problems that slip through layers 1 and 2 are caught here.
This 3-layer structure elevates the tofu problem from "preventable if you know about it" to "prevented by design."
File Structure Improvement
Guidelines were split into a separate file:
.claude/skills/devio/
├── SKILL.md # Entry point
├── article.md # Article creation
├── publish.md # Publishing flow (references svg-guidelines.md)
├── svg-guidelines.md # SVG diagram guidelines (separate file)
└── scripts/
└── svg_to_png.py # SVG → PNG conversion
By separating the guidelines that were embedded in publish.md into svg-guidelines.md as an independent file, it became possible to reference them from other workflows in the future.
Summary
- SVG + cairosvg is best for blog article diagram generation. No ceiling on visual quality
- Mermaid has high layout stability but has limits on visual customization. Effective as an alternative when complex arrow routing is needed
- Excalidraw is good for hand-drawn style use cases but unsuitable for technical blog diagrams
- For stabilizing skill quality, specific templates and rules are more effective than vague instructions
- "The amount of code the LLM writes" is not a decision criterion. What matters is the quality of the output