name: excalidraw-diagram-gen
description: Generate Excalidraw diagram JSON. Use when user requests flowcharts, architecture diagrams, sequence diagrams, ER diagrams, or asks to convert descriptions into Excalidraw format.
Excalidraw Diagram Generation
Generate complete .excalidraw JSON files from user input.
Input Types
- Natural language description
- Image (when vision capable)
Output Format
Output complete .excalidraw JSON:
{
"type": "excalidraw",
"version": 2,
"source": "llm-generated",
"elements": [...],
"appState": {
"viewBackgroundColor": "#ffffff",
"gridSize": null
},
"files": {}
}
Layout Algorithm
1. Starting coordinates (100, 100)
2. Node spacing: horizontal 200px, vertical 150px
3. Flowcharts layout top-to-bottom or left-to-right
4. Architecture diagrams partition by tier
5. Node width 120-200px, height 60-80px
6. Text centered within container
7. For large diagrams, use `frame` to partition sections; set children `frameId` to frame `id`
8. Frame ordering: all frame children must appear before the frame element in `elements[]`
Element Generation Rules
Each element must include:
- `id`: unique string, format `elem_${type}_${index}`
- `type`: rectangle | diamond | ellipse | arrow | line | text | frame
- `x`, `y`: coordinates
- `width`, `height`: dimensions
- `angle`: 0
- `strokeColor`: "#1e1e1e"
- `backgroundColor`: "#a5d8ff" for shapes, "#ffec99" for decisions
- `fillStyle`: "solid"
- `strokeWidth`: 2
- `strokeStyle`: "solid"
- `roundness`: `null` (or `{ "type": 3 }` for rounded rectangles)
- `roughness`: 0 (use 1 only when user asks for hand-drawn look)
- `opacity`: 100
- `seed`: random integer
- `version`: 1
- `versionNonce`: random integer
- `isDeleted`: false
- `groupIds`: []
- `frameId`: null
- `boundElements`: `null` or bound arrows/text
- `updated`: current timestamp
- `link`: null
- `locked`: false
- `index`: null
Arrow element additional properties:
- `points`: [[0,0], [dx, dy]] relative coordinate array
- `startBinding`/`endBinding`: `{ elementId, fixedPoint, mode: "inside" }`
- Choose `fixedPoint` by comparing start/end centers:
- if `abs(dx) >= abs(dy)`: start right `[1, 0.5]` -> end left `[0, 0.5]` (or reversed if dx < 0)
- else: start bottom `[0.5, 1]` -> end top `[0.5, 0]` (or reversed if dy < 0)
- `startArrowhead`: null
- `endArrowhead`: "arrow"
- `elbowed`: false
Line element additional properties:
- `points`: [[0,0], [dx, dy]] relative coordinate array
- `startBinding`/`endBinding`: `{ elementId, fixedPoint, mode: "inside" }` or null
- `startArrowhead`: null
- `endArrowhead`: null
- `polygon`: false
Frame element additional properties:
- `type`: "frame"
- `name`: string or null
- Typical style: `backgroundColor: "transparent"`, `strokeStyle: "dashed"`, `roughness: 0`, `locked: true`
- Children elements inside the frame must set `frameId: frame.id`
- Ordering requirement: frame children first, then the frame element
Text element additional properties:
- `fontSize`: 20
- `fontFamily`: 2 (use 1 only when user asks for casual/hand-drawn look)
- `text`: display text
- `textAlign`: "center"
- `verticalAlign`: "middle"
- `containerId`: container element ID (when bound to shape)
- `originalText`: same as text
- `autoResize`: true
- `lineHeight`: 1.25
Line/arrow semantics:
- Primary flow: `strokeStyle: "solid"`
- Return/async/optional: `strokeStyle: "dashed"`
- Dependency/reference: `strokeStyle: "dotted"`Color semantics (suggested):
- Info/input/user: background
#a5d8ff
- Success/data/store: background
#b2f2bb
- Decision/warn: background
#ffec99
- Error/stop: background
#ffc9c9
Default (technical/pro): roughness: 0, fontFamily: 2, gridSize: null
Casual (sketch): roughness: 1, fontFamily: 1
Binding Rules
1. Text bound to container: set text's `containerId` to container ID, container's `boundElements` includes `{ id: textId, type: "text" }`
2. Arrow bound to shape: set arrow's `startBinding`/`endBinding` to shape info, shape's `boundElements` includes `{ id: arrowId, type: "arrow" }`
3. fixedPoint coordinates: [0.5, 0] = top center, [0.5, 1] = bottom center, [0, 0.5] = left center, [1, 0.5] = right center
Diagram Type Templates
Node type mapping:
- Start/End: ellipse, backgroundColor "#b2f2bb"
- Process: rectangle, backgroundColor "#a5d8ff"
- Decision: diamond, backgroundColor "#ffec99"
- Subprocess: rectangle + double border effectSwimlanes (optional):
- Use lane containers as large rectangles with
backgroundColor: "transparent", strokeStyle: "dashed", locked: true
- Lane title as a text element near top-left of lane
- Keep nodes visually within their lane (or group with a
frame)
Tier layout:
- Client tier y=100
- Service tier y=300
- Data tier y=500
Nodes arranged horizontally within each tier, spacing 200px
Participants arranged horizontally y=100, spacing 200px
Message arrows increment vertically, y += 80 per message
Lifelines represented with dashed linesLifeline element:
type: "line", strokeStyle: "dashed", strokeWidth: 1, roughness: 0, polygon: false
Message conventions:
- Call: solid arrow
- Return: dashed arrow
Output Requirements
- MUST generate valid JSON importable to Excalidraw
- MUST ensure all element IDs unique
- MUST set binding relationships correctly
- MUST use relative coordinates for arrow points
- NEVER generate image type elements
- NEVER omit required fields
- Avoid
freedraw unless user explicitly asks (large diagrams)
Acceptance Checklist