
Claude Codeスキルで図表生成を最適化した話:SVG vs Mermaid vs Excalidraw 比較と設計判断
はじめに
DevelopersIOの記事を書くとき、技術的な概念を説明する図表があると読者の理解が格段に深まります。しかし、毎回手動で図を作るのは面倒です。
そこでClaude Codeのスキル機能を使い、記事公開時にSVGで図表を自動生成し、PNGに変換するパイプラインを構築しています。しかし、生成される図の品質にばらつきがありました。「もっと良い方法があるのでは?」と思い、SVG(cairosvg)、Mermaid CLI、Excalidrawの3つのアプローチを実際に比較検証してみました。
この記事では、その比較結果と、最終的にスキルの設計をどう改善したかを共有します。
前提・環境
- Claude Code
- macOS(Apple Silicon)
- Python 3.14 +
uv(パッケージ管理) - cairosvg(SVG → PNG変換)
@mermaid-js/mermaid-cli(Mermaid → PNG変換)- Playwright(Excalidrawレンダリング)
3つのアプローチの概要
現在のSVGパイプラインは以下のフローで動作しています:

このパイプラインを他のアプローチと比較しました:
| アプローチ | 仕組み | Claudeが書くもの |
|---|---|---|
| SVG + cairosvg | ClaudeがSVGコードを生成 → cairosvgでPNG変換 | SVG(座標・スタイル含む) |
| Mermaid CLI | ClaudeがMermaid記法を生成 → mmdc(Puppeteer)でPNG変換 | Mermaid テキスト構文 |
| Excalidraw | ClaudeがExcalidraw JSONを生成 → Playwright経由でPNG変換 | Excalidraw JSON(座標含む) |
Round 1: シンプルなワークフロー図
最初のテストとして、3フェーズのワークフロー図(計画→実装→レビュー)を同じ概念で3つのアプローチで生成しました。
SVG + cairosvg の結果
- デザイン: グラデーションヘッダー、ドロップシャドウ、バッジアイコン(H/AI/OK)。最もモダンな見た目
- 日本語: 豆腐(□□□□)になった。
font-familyにヒラギノフォントを指定し忘れたのが原因 - レイアウト: 手動座標配置だが、このシンプルさなら問題なし

Mermaid CLI の結果
- デザイン: 標準的なダイアグラムツールの見た目。
classDefでノード色は変えられるが、グラデーションやシャドウは不可 - 日本語: 完璧に表示。Puppeteerが実ブラウザで描画するため
- レイアウト: 自動レイアウトエンジンが配置を担当。手動調整不要

Excalidraw の結果
- デザイン: 手書き風の線。技術ブログにはやや合わない
- 日本語: 表示されるが荒い
- レイアウト: テキストがボックスからはみ出す、座標ずれ。SVGと同じ「手動座標配置」問題がある上に、フィードバックが効きにくい

Round 2: 複雑なCI/CDパイプライン
「シンプルな図ならSVGでいいけど、複雑な図は矢印が崩れるのでは?」という疑問があったため、15ノード・並列分岐・フィードバックループを含むCI/CDパイプライン図で再テストしました。Round 1でExcalidrawはレイアウト品質が低かったため、Round 2ではSVGとMermaidの2つに絞っています。
SVG + cairosvg
- 並列分岐(3テストの同時実行)、ダイヤモンド型の決定ノード、破線のフィードバックループ、ロールバックパス — すべて正しくレンダリング
- 矢印の交差もなし。複雑でも崩れなかった
- フォントをヒラギノに修正すれば、日本語も問題なく表示される

Mermaid CLI
- 自動レイアウトで矢印の交差ゼロ。安定
- ただし、OK/NG分岐の配置が直感と異なる方向に流れることがある
- 視覚的にはフラットで、複雑な図ほどSVGとの品質差が目立つ

比較まとめ
| 観点 | SVG + cairosvg | Mermaid | Excalidraw |
|---|---|---|---|
| ビジュアル品質 | 最高(グラデーション、シャドウ、バッジ) | 中(フラットデザイン) | 低(手書き風、テキストはみ出し) |
| 日本語対応 | ヒラギノフォント指定で解決 | 自動で対応 | 動作するが荒い |
| レイアウト安定性 | 手動だが、Claudeが適切に配置すればOK | 最高(自動レイアウト) | 手動座標 + 低品質 |
| 人間の作業量 | 同じ(自然言語でClaude指示) | 同じ | 同じ |
| ビジュアルの上限 | 無制限(ピクセルレベルの制御) | 固定(Mermaidのテーマ機能まで) | 手書き風に固定 |
重要な発見: 「記述コスト」は無関係
当初「SVGは200行、Mermaidは30行で済む」ことを重視していました。しかし実際にはClaudeがコードを書くので、人間のコスト(自然言語で図を説明する)は3つとも同じです。記述量の差は判断基準になりません。
結論: SVG + cairosvg を継続
公開ブログの図表にはビジュアル品質を優先し、SVGアプローチを採用しました。日本語の豆腐問題はフォント指定で解決できる既知の問題です。
スキルへの反映: 何を改善したか
比較検証の結果を踏まえ、スキルのSVGガイドラインを大幅に強化しました。
改善前(7行の曖昧な指示)
- シンプルで読みやすいデザイン。装飾は最小限
- 配色: 白背景、青系アクセント、グレー補助
- フォント: Hiragino Sans 指定
- 幅: 800px 以内
これだけでは、セッションごとにClaude が異なるスタイルで図を生成し、品質にばらつきが出ていました。
改善後: 4つの柱
1. セマンティックカラーパレット
色を「用途」で定義しました:
| 用途 | メイン | サブ/背景 |
|---|---|---|
| 通常フロー | #3B82F6 |
#DBEAFE |
| 成功/完了 | #10B981 |
#D1FAE5 |
| エラー/NG | #EF4444 |
#FEE2E2 |
| 警告/判断 | #F59E0B |
#FEF3C7 |
「青/グレー」ではなく意味ベースで色を定義することで、どのセッションでも一貫したデザインになります。
2. <defs> テンプレート
SVGの共通パーツ(シャドウフィルター、矢印マーカー、グラデーション)をテンプレートとして提供:
<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>
毎回ゼロからスタイルを考える必要がなくなりました。
3. デザインパターンの定義
「カード型コンテナ」「バッジ」「決定ノード」など、図で繰り返し使うパターンを名前付きで定義しました。「グラデーションヘッダー付きの角丸カード」を毎回発明する必要がなくなります。
4. 複雑さの制限
SVGの弱点(手動座標配置)を認めた上で、崩れを防ぐルールを設けました:
- ノード数12以下
- 矢印交差2箇所以上は分割
- 3階層以上のネストは禁止
日本語豆腐問題の実装レベルの対策
Round 1で発覚した豆腐問題は「フォントを指定すれば直る」と一言で片付けられがちですが、実際のスキルでは3層の防御で再発を防いでいます。
層1: ルートレベルのフォント指定(必須ルール)
ガイドラインに以下を明記しました:
フォント: font-family="Hiragino Sans, Hiragino Kaku Gothic ProN, sans-serif"(必須)
ポイントはルート <svg> 要素に設定することです。CSS の継承により子要素すべてに適用されるため、個別の <text> にフォントを指定し忘れる事故を防げます。sans-serif だけだと cairosvg が日本語グリフを見つけられず豆腐になります。
層2: Unicode特殊文字の禁止
cairosvg はフォントに含まれない記号も豆腐にします。✓、✗、≥ などの Unicode 特殊文字は禁止し、代替手段を指定しました:
| NG | 代替 |
|---|---|
✓ |
SVGで円+チェックマーク図形を描画 |
✗ |
SVGで×図形を描画 |
≥ |
ASCII の >= |
フォントを正しく指定しても、フォントに含まれないグリフは豆腐になります。この層はその盲点をカバーします。
層3: 変換後の目視確認ループ
最後の砦として、PNG変換後にClaude自身がReadツールで画像を読み込み、レンダリング結果を確認するルールを設けています:
変換後は必ず Read ツールで PNG を読み込み、レンダリング結果を目視確認する。
問題があれば SVG を修正して再変換し、再度確認する。
問題がないことを確認してから SVG ファイルを削除し PNG のみ残す。
Claude はマルチモーダル LLM なので、PNG を読み込めば豆腐やラベルの重なりを自分で検出できます。層1・層2をすり抜けた問題もここで捕捉されます。
この3層構造により、豆腐問題は「知っていれば防げる」レベルから「仕組みで防ぐ」レベルに引き上げられました。
ファイル構成の改善
ガイドラインを独立ファイルに切り出しました:
.claude/skills/devio/
├── SKILL.md # エントリポイント
├── article.md # 記事作成
├── publish.md # 公開フロー(svg-guidelines.md を参照)
├── svg-guidelines.md # SVG図表ガイドライン(独立ファイル)
└── scripts/
└── svg_to_png.py # SVG → PNG 変換
publish.md に埋め込まれていたガイドラインを svg-guidelines.md として独立させたことで、将来別のワークフローからも参照可能になりました。
まとめ
- SVG + cairosvg がブログ記事の図表生成には最適。ビジュアル品質の上限がない
- Mermaid はレイアウト安定性が高いが、見た目のカスタマイズに限界がある。複雑な矢印ルーティングが必要な場合の代替として有効
- Excalidraw は手書き風の用途には良いが、技術ブログの図表には不向き
- スキルの品質安定化には、曖昧な指示よりも具体的なテンプレートとルールが効果的
- 「LLMが書くコードの量」は判断基準にならない。重要なのは出力の品質




