Excalidraw Diagram Design Guide
Color Palette
Stroke Colors (borders & text)
| Name | Hex | Use for |
|---|---|---|
| Black | #1e1e1e | Default text & borders |
| Red | #e03131 | Errors, warnings, critical |
| Green | #2f9e44 | Success, approved, healthy |
| Blue | #1971c2 | Primary actions, links |
| Purple | #9c36b5 | Services, middleware |
| Orange | #e8590c | Async, queues, events |
| Cyan | #0c8599 | Data stores, databases |
| Gray | #868e96 | Annotations, secondary |
Fill Colors (backgroundColor — pastel)
| Name | Hex | Pairs with stroke |
|---|---|---|
| Light Red | #ffc9c9 | #e03131 |
| Light Green | #b2f2bb | #2f9e44 |
| Light Blue | #a5d8ff | #1971c2 |
| Light Purple | #eebefa | #9c36b5 |
| Light Orange | #ffd8a8 | #e8590c |
| Light Cyan | #99e9f2 | #0c8599 |
| Light Gray | #e9ecef | #868e96 |
| White | #ffffff | #1e1e1e |
Sizing Rules
- Minimum shape: width >= 120px, height >= 60px
- Shape width formula:
max(160, charCount * 11 + 40)— the+40is mandatory padding, never skip it - Multi-word labels: measure the longest single word:
max(160, longestWord * 11 + 80) - Shape height: 60px single-line, 80px two-line, 100px three-line labels
- Font sizes: body text >= 16, titles/headers >= 20, small labels >= 14
- Padding: at least 20px inside shapes for text breathing room
- Arrow gap: minimum 80px between connected shapes — closer = arrows overdraw the border
- Consistent sizing: same-role shapes = same dimensions
Layout Patterns
- Grid snap: align to 20px grid for clean layouts
- Spacing: 40–80px gap between adjacent shapes
- Flow direction: top-to-bottom (vertical) or left-to-right (horizontal)
- Hierarchy: important nodes larger or higher; left-to-right = temporal order
- Grouping: cluster related elements; use background rectangles as zones
- Tier layout:
- Tier 1 (y=50–130): Client apps / entry points
- Tier 2 (y=200–280): Gateway / edge layer
- Tier 3 (y=350–440): Services (spread wide: 160–200px apart)
- Tier 4 (y=510–590): Data stores
- Side panels: x < 0 or x > mainDiagramRight + 80
Arrow Best Practices
Binding (always use element IDs, not raw coordinates)
{"type": "arrow", "x": 0, "y": 0, "start": {"id": "svc-a"}, "end": {"id": "svc-b"}}
Server auto-routes arrows to element edges using precise geometry.
Line styles
- Solid: synchronous calls, direct dependencies
- Dashed (
"strokeStyle": "dashed"): async flows, optional paths, events - Dotted (
"strokeStyle": "dotted"): weak dependencies, annotations
Arrowheads
"endArrowhead": "arrow"— default directed flow"endArrowhead": "dot"— data stores / database relationships"endArrowhead": "bar"— cardinality (ER diagrams)"endArrowhead": "triangle"— filled triangle (UML)"endArrowhead": null— plain line (undirected)"startArrowhead"mirrors the same options for bidirectional arrows
Labels on arrows
Use "label": {"text": "HTTP"} — keep to 1–2 words. Long labels overlap shapes.
Routing complex arrows (avoid crossings)
Elbowed arrow (right-angle routing — cleanest for architecture diagrams):
{
"type": "arrow", "x": 0, "y": 0,
"start": {"id": "svc-a"},
"end": {"id": "svc-b"},
"elbowed": true
}
Curved arc (for arrows that need to arc over elements):
{
"type": "arrow", "x": 100, "y": 100,
"points": [[0,0],[50,-40],[200,0]],
"roundness": {"type": 2},
"strokeColor": "#1971c2"
}
Fill Styles (fillStyle)
Controls how shape interiors are rendered. Default is "hachure" (Excalidraw's signature sketchy look).
| Value | Appearance | Best for |
|---|---|---|
"solid" | Flat solid color | Clean production diagrams |
"hachure" | Diagonal hatching (default) | Sketchy/hand-drawn style |
"cross-hatch" | Grid hatching | Emphasis, dense areas |
"dots" | Dot pattern | Light texture, secondary elements |
"zigzag" | Zigzag lines | Decorative, callouts |
"zigzag-line" | Single zigzag | Borders/edges |
Use "solid" for any diagram meant to look professional. Only use "hachure" if you want the hand-drawn aesthetic intentionally.
{"type": "rectangle", "fillStyle": "solid", "backgroundColor": "#a5d8ff", ...}
Rounded Corners (roundness)
Add "roundness": {"type": 3} to rectangle and ellipse elements for rounded corners.
{"type": "rectangle", "roundness": {"type": 3}, ...}
Omit roundness (or set to null) for sharp corners.
Diagram Type Templates
Architecture Diagram
{
"elements": [
{
"id": "zone-backend",
"type": "rectangle",
"x": 40, "y": 40, "width": 600, "height": 400,
"backgroundColor": "#e9ecef", "strokeColor": "#868e96",
"opacity": 40,
"label": {"text": "Backend", "fontSize": 20}
},
{
"id": "api-gw",
"type": "rectangle",
"x": 80, "y": 100, "width": 180, "height": 70,
"strokeColor": "#9c36b5", "backgroundColor": "#eebefa",
"label": {"text": "API Gateway"}
},
{
"id": "auth-svc",
"type": "rectangle",
"x": 80, "y": 240, "width": 180, "height": 70,
"strokeColor": "#1971c2", "backgroundColor": "#a5d8ff",
"label": {"text": "Auth Service"}
},
{
"id": "db",
"type": "rectangle",
"x": 80, "y": 380, "width": 180, "height": 70,
"strokeColor": "#0c8599", "backgroundColor": "#99e9f2",
"label": {"text": "Postgres"}
},
{"type":"arrow","x":0,"y":0,"start":{"id":"api-gw"},"end":{"id":"auth-svc"},"label":{"text":"JWT verify"}},
{"type":"arrow","x":0,"y":0,"start":{"id":"auth-svc"},"end":{"id":"db"},"label":{"text":"SQL"},"strokeStyle":"dashed"}
]
}
Flowchart
{
"elements": [
{"id":"start","type":"ellipse","x":160,"y":40,"width":120,"height":60,
"strokeColor":"#2f9e44","backgroundColor":"#b2f2bb","label":{"text":"Start"}},
{"id":"step1","type":"rectangle","x":140,"y":160,"width":160,"height":60,
"strokeColor":"#1971c2","backgroundColor":"#a5d8ff","label":{"text":"Validate Input"}},
{"id":"decide","type":"diamond","x":140,"y":280,"width":160,"height":80,
"strokeColor":"#e8590c","backgroundColor":"#ffd8a8","label":{"text":"Valid?"}},
{"id":"end-ok","type":"ellipse","x":340,"y":290,"width":100,"height":60,
"strokeColor":"#2f9e44","backgroundColor":"#b2f2bb","label":{"text":"Success"}},
{"id":"end-err","type":"ellipse","x":0,"y":290,"width":100,"height":60,
"strokeColor":"#e03131","backgroundColor":"#ffc9c9","label":{"text":"Error"}},
{"type":"arrow","x":0,"y":0,"start":{"id":"start"},"end":{"id":"step1"}},
{"type":"arrow","x":0,"y":0,"start":{"id":"step1"},"end":{"id":"decide"}},
{"type":"arrow","x":0,"y":0,"start":{"id":"decide"},"end":{"id":"end-ok"},"label":{"text":"Yes"}},
{"type":"arrow","x":0,"y":0,"start":{"id":"decide"},"end":{"id":"end-err"},"label":{"text":"No"}}
]
}
ER Diagram
{
"elements": [
{"id":"users","type":"rectangle","x":40,"y":100,"width":180,"height":120,
"strokeColor":"#1971c2","backgroundColor":"#a5d8ff",
"label":{"text":"users\n─────\nid: UUID\nname: text\nemail: text"}},
{"id":"orders","type":"rectangle","x":300,"y":100,"width":180,"height":120,
"strokeColor":"#9c36b5","backgroundColor":"#eebefa",
"label":{"text":"orders\n──────\nid: UUID\nuser_id: UUID\ntotal: decimal"}},
{"type":"arrow","x":0,"y":0,"start":{"id":"users"},"end":{"id":"orders"},
"label":{"text":"1..N"},"endArrowhead":"arrow","startArrowhead":"dot"}
]
}
Mindmap (Clean Radial, 5 Branches)
Use this when a user asks for a minimal mindmap with directional branches.
Rules:
- Keep one center node and place first-level branches radially around it (not in a loose grid).
- Keep all labels inside shape text; never leave branch words floating outside boxes.
- Use bound arrows with
start/endIDs only. - Keep branch lengths similar unless direction intentionally emphasizes a topic.
Reference coordinates (centered canvas):
- Center:
(560, 320) - Branch vectors: up
(0,-180), right(240,-40), down-right(220,190), down-left(-220,190), left(-240,-40) - Child vectors from each branch: continue same direction by 160-220px.
Coordinate note:
- Element
x/yvalues are top-left anchors; evaluate radial balance using node centers, not top-left corners.
{
"elements": [
{"id":"center","type":"ellipse","x":560,"y":320,"width":220,"height":100,
"strokeColor":"#374151","backgroundColor":"#f3f4f6","fillStyle":"solid","roundness":{"type":3},
"label":{"text":"Focus Topic"}},
{"id":"b1","type":"rectangle","x":560,"y":140,"width":190,"height":60,
"strokeColor":"#1f2937","backgroundColor":"#ffffff","fillStyle":"solid","roundness":{"type":3},
"label":{"text":"Branch 1"}},
{"id":"b2","type":"rectangle","x":800,"y":280,"width":190,"height":60,
"strokeColor":"#1f2937","backgroundColor":"#ffffff","fillStyle":"solid","roundness":{"type":3},
"label":{"text":"Branch 2"}},
{"id":"b3","type":"rectangle","x":780,"y":510,"width":190,"height":60,
"strokeColor":"#1f2937","backgroundColor":"#ffffff","fillStyle":"solid","roundness":{"type":3},
"label":{"text":"Branch 3"}},
{"id":"b4","type":"rectangle","x":340,"y":510,"width":190,"height":60,
"strokeColor":"#1f2937","backgroundColor":"#ffffff","fillStyle":"solid","roundness":{"type":3},
"label":{"text":"Branch 4"}},
{"id":"b5","type":"rectangle","x":320,"y":280,"width":190,"height":60,
"strokeColor":"#1f2937","backgroundColor":"#ffffff","fillStyle":"solid","roundness":{"type":3},
"label":{"text":"Branch 5"}},
{"id":"c1","type":"rectangle","x":560,"y":-30,"width":180,"height":52,
"strokeColor":"#6b7280","backgroundColor":"#ffffff","fillStyle":"solid","roundness":{"type":3},
"label":{"text":"Detail 1"}},
{"id":"c2","type":"rectangle","x":1060,"y":240,"width":180,"height":52,
"strokeColor":"#6b7280","backgroundColor":"#ffffff","fillStyle":"solid","roundness":{"type":3},
"label":{"text":"Detail 2"}},
{"id":"c3","type":"rectangle","x":1030,"y":640,"width":180,"height":52,
"strokeColor":"#6b7280","backgroundColor":"#ffffff","fillStyle":"solid","roundness":{"type":3},
"label":{"text":"Detail 3"}},
{"id":"c4","type":"rectangle","x":100,"y":640,"width":180,"height":52,
"strokeColor":"#6b7280","backgroundColor":"#ffffff","fillStyle":"solid","roundness":{"type":3},
"label":{"text":"Detail 4"}},
{"id":"c5","type":"rectangle","x":40,"y":240,"width":180,"height":52,
"strokeColor":"#6b7280","backgroundColor":"#ffffff","fillStyle":"solid","roundness":{"type":3},
"label":{"text":"Detail 5"}},
{"type":"arrow","x":0,"y":0,"start":{"id":"center"},"end":{"id":"b1"},"strokeColor":"#9ca3af","endArrowhead":"arrow"},
{"type":"arrow","x":0,"y":0,"start":{"id":"center"},"end":{"id":"b2"},"strokeColor":"#9ca3af","endArrowhead":"arrow"},
{"type":"arrow","x":0,"y":0,"start":{"id":"center"},"end":{"id":"b3"},"strokeColor":"#9ca3af","endArrowhead":"arrow"},
{"type":"arrow","x":0,"y":0,"start":{"id":"center"},"end":{"id":"b4"},"strokeColor":"#9ca3af","endArrowhead":"arrow"},
{"type":"arrow","x":0,"y":0,"start":{"id":"center"},"end":{"id":"b5"},"strokeColor":"#9ca3af","endArrowhead":"arrow"},
{"type":"arrow","x":0,"y":0,"start":{"id":"b1"},"end":{"id":"c1"},"strokeColor":"#9ca3af","endArrowhead":"arrow"},
{"type":"arrow","x":0,"y":0,"start":{"id":"b2"},"end":{"id":"c2"},"strokeColor":"#9ca3af","endArrowhead":"arrow"},
{"type":"arrow","x":0,"y":0,"start":{"id":"b3"},"end":{"id":"c3"},"strokeColor":"#9ca3af","endArrowhead":"arrow"},
{"type":"arrow","x":0,"y":0,"start":{"id":"b4"},"end":{"id":"c4"},"strokeColor":"#9ca3af","endArrowhead":"arrow"},
{"type":"arrow","x":0,"y":0,"start":{"id":"b5"},"end":{"id":"c5"},"strokeColor":"#9ca3af","endArrowhead":"arrow"}
]
}
Anti-Patterns to Avoid
- Overlapping elements — always leave gaps; use
excalidraw distribute - Cramped spacing — minimum 40px between shapes; 60px between diagram tiers
- Tiny fonts — never below 14px; prefer 16+ for readability
- Raw arrow coordinates — always use
start/endbinding to connect to shapes - Too many colors — limit to 3–4 fill colors per diagram
- Inconsistent sizes — same-role shapes should have identical width/height
- No labels — every shape and meaningful arrow needs descriptive text
- Flat layouts — use background zones/groups to show hierarchy
- Side panels overlapping main diagram — place at x < 0 or x > mainRight + 80
- Unchecked arrow crossings — use
"elbowed": trueor route with waypoints - Forgetting
fillStyle: "solid"— default is"hachure"(sketchy); always set"fillStyle": "solid"for clean diagrams - Mindmap drift — avoid random placement; use radial vectors from center and continue each branch in the same direction
- Detached labels — if text appears outside a node, fix node label and remove loose text elements
Pre-Drawing Checklist
Before writing any JSON:
- Plan coordinate grid (tiers, x-positions, spacing)
- Calculate shape widths:
max(160, charCount * 11 + 40) - Assign IDs to all shapes that arrows will reference
- Choose 2–3 fill colors for semantic grouping
- Add
"fillStyle": "solid"to every shape for a clean look - Decide flow direction (vertical or horizontal)
- Run
excalidraw guidefor quick color/sizing reference