Building a Mermaid Diagram Editor: From DSL Text to SVG Rendering
Building a Mermaid Diagram Editor: From DSL Text to SVG Rendering#
I was writing documentation the other day and needed a flowchart. Opened draw.io, dragged some shapes around, felt tedious. Then I remembered Mermaid - write simple text syntax, get diagrams. Decided to build an online Mermaid editor with real-time preview and quick export.
What is Mermaid?#
Mermaid is a JavaScript-based diagramming tool. You write text, it generates flowcharts, sequence diagrams, Gantt charts, and more. For example:
flowchart TD
A[Start] --> B{Pass?}
B -->|Yes| C[Process]
B -->|No| D[Retry]
C --> E[End]
D --> B
This “Diagrams as Code” approach is better for version control than drag-and-drop tools. Changes show up clearly in git diffs.
Core Implementation: Dynamic Loading + Debounced Rendering#
Mermaid is heavy - about 1MB minified. We use dynamic imports to avoid slowing down the initial page load:
const mermaidRef = useRef<any>(null)
useEffect(() => {
const loadMermaid = async () => {
const mermaid = (await import('mermaid')).default
mermaid.initialize({
startOnLoad: false,
theme: 'dark'
})
mermaidRef.current = mermaid
setRenderId(1) // trigger first render
}
loadMermaid()
}, [])
The library only loads when the user visits the Mermaid editor page.
Real-time preview needs debouncing. Rendering on every keystroke would be slow:
const debounceRef = useRef<NodeJS.Timeout | null>(null)
useEffect(() => {
if (renderId === 0) return
if (debounceRef.current) clearTimeout(debounceRef.current)
debounceRef.current = setTimeout(() => {
renderMermaid(code)
}, 500)
return () => {
if (debounceRef.current) clearTimeout(debounceRef.current)
}
}, [code, renderId])
We wait 500ms after the user stops typing before rendering.
DSL Parsing and Error Handling#
Mermaid has a parser that converts text DSL to an AST, then renders SVG. Syntax errors throw exceptions:
const renderMermaid = async (value: string) => {
if (!mermaidRef.current || !value.trim()) {
setSvg('')
setError('')
return
}
try {
const id = `mermaid-${Date.now()}`
const { svg } = await mermaidRef.current.render(id, value)
setSvg(svg)
setError('')
} catch (err: any) {
setError(err?.message || String(err))
setSvg('')
}
}
We use Date.now() for unique IDs to avoid conflicts when rendering multiple diagrams. Error messages show directly to help users fix syntax issues.
SVG Export and Memory Cleanup#
After rendering, Mermaid returns an SVG string. Export creates a Blob and triggers download:
const handleDownloadSvg = () => {
if (!svg) return
const blob = new Blob([svg], { type: 'image/svg+xml' })
const url = URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = url
a.download = 'diagram.svg'
a.click()
URL.revokeObjectURL(url) // free memory
}
The key is URL.revokeObjectURL(url) - without it, each export leaks a Blob URL in memory.
Template Switching Design#
We provide 7 templates: flowchart, sequence diagram, class diagram, state diagram, Gantt chart, pie chart, ER diagram. Templates live in an object, switching just replaces the editor content:
const templates: Record<string, string> = {
flowchart: `flowchart TD
A[Start] --> B{Decision}
B -->|Yes| C[Action 1]
B -->|No| D[Action 2]`,
sequence: `sequenceDiagram
participant A as Alice
participant B as Bob
A->>B: Hello Bob`,
// ... other templates
}
const handleTemplateChange = (key: string) => {
setSelectedTemplate(key)
setCode(templates[key])
}
Object dictionary is cleaner than switch-case. Adding a template is just one key-value pair.
Performance Edge Cases#
We hit a few performance issues:
-
Large diagrams: 100+ nodes take 2-3 seconds to render. Show a loading spinner so users don’t think it’s frozen.
-
Rapid template switching: Each switch triggers debounced re-render. Clear the timeout immediately on switch to avoid wasted renders.
-
Huge SVG size: Complex diagrams can produce 500KB+ SVGs. Tools like SVGO can optimize by removing comments and redundant attributes.
Use Cases#
Mermaid shines for:
- Technical docs: Embed flowcharts in README, Markdown supports it natively
- Architecture design: Sequence diagrams for API flows, class diagrams for object relationships
- Project planning: Gantt charts for schedules, state diagrams for business workflows
Compared to drag-and-drop tools, Mermaid is version-control friendly, reusable, and maintainable. Changing a diagram is just editing text - diffs are clear.
Related Tools#
If you work with diagrams and visualizations, these might help too:
- JSON to Chart - Convert JSON data to visual charts
- Excalidraw - Hand-drawn style whiteboard
- Markdown to HTML - Markdown conversion and preview
Keywords: Mermaid diagram editor, DSL rendering, flowchart generator, sequence diagram, SVG export, diagram visualization tool