Generate hand-drawn style diagrams (architecture, flowcharts, system design) as .excalidraw.json files. Use when user wants diagrams, mentions Excalidraw, or needs Mermaid-to-visual conversion.
Generate professional hand-drawn style diagrams in Excalidraw JSON format.
Arrow Binding (MUST follow): Arrows must bind to components bidirectionally:
startBinding and endBinding pointing to component IDsboundElements array listing bound arrow IDsText requires width/height: Text elements must have width and height fields, otherwise they won't render
Arrow labels: Place below arrow (y + 30) or above (y - 30), never overlapping components
Background region sizing (MUST follow): Background regions (subgraphs/phases) must fully cover all contained elements:
width = (maxX + maxWidth) - minX + 80, height = (maxY + maxHeight) - minY + 80No overlaps (MUST follow): Arrows must not cross unrelated components; labels must not overlap components. See "Layout Optimization" section for strategies.
Container binding (MUST follow): When connecting to grouped/nested structures, arrows must bind to the outer container (background region), NOT to internal elements:
dag → main-bg (container), NOT dag → read-main (internal element)Sibling layout (MUST follow): Elements at the same hierarchy level must be placed horizontally (same row), NOT vertically:
Nested structure clarity (MUST follow): When a container has internal elements, ensure clear hierarchy and no overlaps:
rect.height >= text.height + 20)Arrow path space reservation (MUST follow): When arrows connect nested containers, ensure sufficient space for arrow routing:
target.y >= max(child.y + child.height) + 60SVG export requests (MUST follow): If the user asks for SVG output/conversion, ALWAYS convert the generated .excalidraw.json file via https://kroki.io/excalidraw/svg using curl.
Step 1: Arrow Path Analysis Before placing any component, list ALL arrows and their source→target pairs:
Arrow 1: A → B (horizontal)
Arrow 2: B → C (horizontal)
Arrow 3: C → A (return arrow - DANGER: will cross B if horizontal layout)
Step 2: Identify Crossing Risks For each arrow, check: "Does a straight line from source to target pass through any other component?"
Step 3: Choose Layout Strategy Based on crossing risks, select appropriate layout:
Step 4: Verify Before Finalizing After generating JSON, mentally trace each arrow path and confirm:
{
"type": "excalidraw",
"version": 2,
"source": "https://excalidraw.com",
"elements": [],
"appState": { "viewBackgroundColor": "#ffffff" },
"files": {}
}
Rectangle (Component Box)
{
"id": "unique-id",
"type": "rectangle",
"x": 100, "y": 100,
"width": 140, "height": 60,
"strokeColor": "#1e1e1e",
"backgroundColor": "#a5d8ff",
"roundness": { "type": 3 },
"boundElements": [{"id": "arrow-id", "type": "arrow"}]
}
Text (width/height required, fontFamily: 4 required)
{
"id": "unique-id",
"type": "text",
"x": 120, "y": 120,
"width": 80, "height": 24,
"text": "Label",
"fontSize": 16,
"fontFamily": 4,
"textAlign": "center"
}
Text centering formula (to center text inside a rectangle):
text.x = rect.x + (rect.width - text.width) / 2text.y = rect.y + (rect.height - text.height) / 2Arrow
{
"id": "unique-id",
"type": "arrow",
"x": 240, "y": 130,
"points": [[0, 0], [100, 0]],
"startBinding": { "elementId": "source-id", "focus": 0, "gap": 5 },
"endBinding": { "elementId": "target-id", "focus": 0, "gap": 5 },
"endArrowhead": "arrow"
}
Arrow coordinate system:
x, y: absolute position of arrow start pointpoints: relative offsets from (x, y). First point is always [0, 0]x: 100, y: 200, points: [[0,0], [50, 0], [50, 100]] draws L-shaped arrow starting at (100, 200)Background Region - Use rectangle with "opacity": 30
"fillStyle": "solid", "strokeWidth": 2, "roughness": 1,
"opacity": 100, "angle": 0, "seed": 1, "version": 1
| Purpose | Background | Stroke |
|---------|------------|--------|
| Primary / Phase 1 | #a5d8ff | #1971c2 |
| Secondary / Phase 2 | #b2f2bb | #2f9e44 |
| Accent / Shared | #fff3bf | #e67700 |
| Storage / State | #d0bfff | #7048e8 |
140×60opacity: 30For sequence diagrams (multiple participants with message flows):
Layout strategy:
Phase 1 (y: 80-300): [A] -----> [B] -----> [C]
msg1 msg2
[A] <----- [B]
response
Phase 2 (y: 320-500): [A'] ----> [B'] ----> [C']
(duplicate participants at new y)
Key insight: For multi-phase sequence diagrams, duplicate participant boxes in each phase rather than drawing long vertical lifelines. This avoids arrow crossing issues.
When multiple arrows connect to the same component:
focus parameter to offset arrow positions on component edgefocus: -0.5 = upper half, focus: 0.5 = lower half, focus: 0 = centerfocus: -0.5 and focus: 0.5 to separate verticallyWhen arrows would cross unrelated components, restructure the layout:
3 components with return arrow (A→B→C, C→A):
4 components with return arrow (A→B→C→D, D→A):
4+ components in sequence with return arrows:
"points": [[0, 0], [0, -80], [-400, -80], [-400, 0]]
Hub-and-spoke (central component connects to many):
Default assumption: If there's a return arrow, horizontal layout will likely fail—plan for bypass or 2D layout upfront.
Flow with Return Arrow (using bypass path) A → B → C, then C → A (return arrow routes above to avoid crossing B)
Arrow analysis:
{
"type": "excalidraw",
"version": 2,
"source": "https://excalidraw.com",
"elements": [
{"id": "a", "type": "rectangle", "x": 100, "y": 150, "width": 140, "height": 60, "backgroundColor": "#a5d8ff", "strokeColor": "#1971c2", "roundness": {"type": 3}, "boundElements": [{"id": "arr1", "type": "arrow"}, {"id": "arr3", "type": "arrow"}]},
{"id": "a-label", "type": "text", "x": 155, "y": 168, "width": 30, "height": 24, "text": "A", "fontSize": 16, "fontFamily": 4, "textAlign": "center"},
{"id": "b", "type": "rectangle", "x": 340, "y": 150, "width": 140, "height": 60, "backgroundColor": "#b2f2bb", "strokeColor": "#2f9e44", "roundness": {"type": 3}, "boundElements": [{"id": "arr1", "type": "arrow"}, {"id": "arr2", "type": "arrow"}]},
{"id": "b-label", "type": "text", "x": 395, "y": 168, "width": 30, "height": 24, "text": "B", "fontSize": 16, "fontFamily": 4, "textAlign": "center"},
{"id": "c", "type": "rectangle", "x": 580, "y": 150, "width": 140, "height": 60, "backgroundColor": "#d0bfff", "strokeColor": "#7048e8", "roundness": {"type": 3}, "boundElements": [{"id": "arr2", "type": "arrow"}, {"id": "arr3", "type": "arrow"}]},
{"id": "c-label", "type": "text", "x": 635, "y": 168, "width": 30, "height": 24, "text": "C", "fontSize": 16, "fontFamily": 4, "textAlign": "center"},
{"id": "arr1", "type": "arrow", "x": 245, "y": 180, "points": [[0, 0], [90, 0]], "endArrowhead": "arrow", "startBinding": {"elementId": "a", "focus": 0, "gap": 5}, "endBinding": {"elementId": "b", "focus": 0, "gap": 5}},
{"id": "arr2", "type": "arrow", "x": 485, "y": 180, "points": [[0, 0], [90, 0]], "endArrowhead": "arrow", "startBinding": {"elementId": "b", "focus": 0, "gap": 5}, "endBinding": {"elementId": "c", "focus": 0, "gap": 5}},
{"id": "arr3", "type": "arrow", "x": 650, "y": 145, "points": [[0, 0], [0, -60], [-480, -60], [-480, 0]], "endArrowhead": "arrow", "strokeStyle": "dashed", "startBinding": {"elementId": "c", "focus": 0, "gap": 5}, "endBinding": {"elementId": "a", "focus": 0, "gap": 5}},
{"id": "arr3-label", "type": "text", "x": 380, "y": 60, "width": 60, "height": 20, "text": "return", "fontSize": 12, "fontFamily": 4, "textAlign": "center"}
],
"appState": {"viewBackgroundColor": "#ffffff"},
"files": {}
}
{descriptive-name}.excalidraw.jsondocs/ folderIf user explicitly asks for SVG (e.g., "convert to svg", "need svg export"), convert with this command:
curl -sS https://kroki.io/excalidraw/svg \
-H 'Content-Type: application/json' \
--data-binary @diagram.excalidraw.json \
-o diagram.svg
Notes:
*.excalidraw.json)fontFamily: 1=Virgil, 2=Helvetica, 3=Cascadia, 4=Comic Shanns (MUST use for hand-drawn style)strokeWidth usage in software diagrams:
1 (thin): background regions, container borders, secondary connections2 (normal/default): primary components, main flow arrows4 (bold): emphasis, critical paths, highlighted elements"strokeStyle": "dashed"Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer