PlantUML cross-tool migration — D2, Mermaid, and Draw.io workflow and pitfalls
When a team re-picks its diagramming tool, migrating from PlantUML to D2 / Mermaid / Draw.io is common. This post distils the practical migration: which diagrams can be auto-converted, which must be rewritten, how to CI-verify the result, and when to skip migration entirely.
Why migrate?
Reasons that come up often:
- Java team → LangChain → LLM team → D2 + Markdown is the new default
- Data team → whole-company rendering standardised on Mermaid (GitHub-native)
- Design collaboration → swap to a Figma-like tool (Draw.io)
- “Avoid the JVM dependency” → migrate to Mermaid / Graphviz
Before migrating, answer: is the reason technical, or just cognitive cost? PlantUML diagrams are data — migration is data migration — detail loss is unavoidable.
Decision framework: should we?
| Criteria | Migrate | Don’t migrate |
|---|---|---|
| Team size | <10 people | >30 people |
| Diagram count | <50 | >300 |
| Diagram type distribution | 80% flowcharts | mostly UML |
| CI rendering dep | Mutable | internal plantuml server already wired |
| Design collaboration | Design-led | Engineering-led |
| CJK / complex chars | Important | Not important |
| Maintenance horizon | <6 months | Long-term (1-2y) |
If “don’t migrate”:
- Keep PlantUML → upgrade to TeaVM WASM → render locally in the browser, fully JVM-free.
- Maintain the plantuml server → team SSR mode, zero client dependency.
If “migrate”: continue reading.
PlantUML → Mermaid
Automatic conversion is limited
Mermaid doesn’t read PlantUML — you need conversion. Reason: PlantUML and Mermaid syntax diverge widely:
| Concept | PlantUML | Mermaid |
|---|---|---|
| Declaration | @startuml ... @enduml |
```mermaid\n...\n``` |
| Direction arrow | Alice -> Bob |
Alice ->> Bob |
| Async | Alice ->> Bob |
Alice ->> Bob (same) |
| Class | class User |
class User { } |
| Note | note left of X |
Note over X |
| Auto-number | (no native) | autonumber |
Hand-conversion example
PlantUML sequence:
1 | @startuml |
Mermaid sequence (manually translated):
1 | sequenceDiagram |
Semi-automatic tools
puml2mermaid— community package, coverage ~50%- ✅ sequence diagrams (simple)
- ✅ class diagram (loose)
- ❌ state diagram
- ❌ component diagram
- ❌ nested package / skinparam
In practice: hand-writing 2 min/diagram vs using the tool 5 min + repeated touch-ups — hand-writing is usually faster.
PlantUML → D2
D2 itself supports plantuml import
D2 in v0.6+ supports D2 reading plantuml:
1 | d2 --plantuml=path/to/diagram.puml out.svg |
But only one direction: puml → D2-equivalent source, then D2 renders. Native conversion quality:
- ✅ sequence diagram (basic)
- ✅ class diagram (basic)
- ⚠️ activity diagram loses
if/elsenesting - ❌ state diagram errors out directly
Converted D2 looks like
Original puml sequence:
1 | Alice -> Bob: hi |
D2:
1 | shape: sequence_diagram |
D2 declares the type with shape: sequence_diagram.
Semi-auto vs hand-write
Complex diagrams (>30 nodes, nested packages): hand-write D2 directly — the tool only helps on simple cases.
Cautions when auto-converting via D2
D2’s plantuml parser is sensitive to colons, quotes, CJK:
1 | Alice -> Bob: 包含:冒号 # ❌ D2 parses as multiple messages |
Any PlantUML “message contains special character” must be quoted before migration.
PlantUML → Draw.io
Draw.io uses XML; there’s no official PlantUML-to-Draw.io converter.
Manual workflow
1 | # 1. Render the puml to SVG |
Draw.io preserves the rough layout, but styles, class inheritance, notes are all lost — usually not worth it.
When to migrate to Draw.io
- Team members need to manually tweak positions.
- You need to mix “flowchart + rectangles + arrows” in a non-standard diagram.
- You need shape libraries / templates.
- You don’t want to use a code editor.
Draw.io’s core benefit is WYSIWYG — once you migrate, you can’t go back to PlantUML editing — the source is gone.
PlantUML → Graphviz DOT
Common in academic / automation scenarios. Open-source tool:
1 | # https://github.com/yegor256/plantuml2dot |
Supports:
- ✅ component diagram
- ✅ class diagram (simple)
- ⚠️ sequence diagram produces ugly DOT (no sequence concept)
Per-diagram-type migration difficulty
| Diagram type | PlantUML → Mermaid | PlantUML → D2 | PlantUML → Draw.io |
|---|---|---|---|
| sequence | medium (manual) | low (official) | high (manual SVG import) |
| class | medium | medium | medium |
| state | high (no native equivalent) | high | high |
| activity | high | high | medium |
| component | low (none) | low (none) | medium |
| usecase | high | high | medium |
| object | medium (classDiagram emulation) | high | medium |
| ER | medium | medium | medium |
| gantt | medium (mermaid native) | medium | high |
| mindmap | medium | low (both native) | low |
Conclusions:
- sequence / class → Mermaid / D2 work out of the box; lowest migration cost.
- state / activity / usecase → all tools fall short; don’t migrate, keep PlantUML.
- mindmap → any tool works.
Migration workflow (recommended in practice)
Step 1: inventory
1 | # List all puml files |
1 | # Detect the diagram type per file |
Step 2: group-by-type migration
1 | # Sequence → Mermaid |
For each diagram, hand-translate → write .mmd file → verify with mermaid CLI.
Step 3: CI consistency verification
1 | # Render → compare structural information |
CI passes → migration complete.
Step 4: parallel-running period
Don’t delete PlantUML files immediately after migration:
1 | docs/diagrams/ |
Three months later, confirm the mermaid version is stable in use, then delete the puml files.
When NOT to migrate
Strongly advise against migration in these scenarios:
- Large UML projects (>50 UML static diagrams) — PlantUML is the industry standard.
- CI already has a PlantUML server — no urgency.
- Diagrams are reverse-engineered (Java → UML) — Draw.io can’t reverse-engineer.
- You need
!include/!function/!definePlantUML-exclusive features — other DSLs don’t have them. - CJK content + large diagrams — PlantUML + Noto font combo is currently the steadiest.
Reverse migration (D2/Mermaid → PlantUML)
Sometimes “we used D2 for a year and want to switch back” or “team merge, diagrams need to be uniform”.
D2 → PlantUML
D2 official provides d2 –plantuml output for reverse-generation, but outputs fragments, not a complete .puml.
Practical approach: hand-write or write a script that scans the D2 syntax tree.
1 | # scripts/d2_to_puml.py |
Mermaid → PlantUML
No official tool; community scripts:
mermaid2plantuml— 40% coverage
In practice, hand-writing is faster.
A set of migration helper scripts
One-shot puml → mmd trial in the repo
1 |
|
In practice 80% is manual.
The decision for puml.online specifically
Our project doesn’t need migration:
- Current primary diagram types: state, class, sequence — 5-8 each
- CI already has hexo generator rendering PlantUML
- CJK + Chinese markdown annotations are dense
- Diagram count will keep growing
Migrating gives no upside — we’d migrate then migrate back.
But for your project: check the decision table above before migrating.
Recap
- PlantUML → Mermaid: simple diagrams 1:1, state/activity come up short
- PlantUML → D2: official reverse-import, but only basic diagrams covered
- PlantUML → Draw.io: effectively “import SVG” + re-position, source is lost
- 80% of migration cost is “manual rewrite” not “auto-conversion”
- More often than not, don’t migrate — PlantUML is the steadiest UML DSL
Next
- Title: PlantUML cross-tool migration — D2, Mermaid, and Draw.io workflow and pitfalls
- Author: puml.online
- Created at : 2026-07-30 12:01:00
- Updated at : 2026-08-14 21:34:29
- Link: https://puml.online/blog/plantuml-migrate-to-d2-mermaid-en/
- License: This work is licensed under CC BY-NC-SA 4.0.