# Excalidraw Element Format Reference This reference documents the element JSON format accepted by the Excalidraw MCP `create_view` tool and the `export_png.mjs` script. ## Color Palette ### Primary Colors | Name | Hex | Use | |------|-----|-----| | Blue | `#4a9eed` | Primary actions, links | | Amber | `#f59e0b` | Warnings, highlights | | Green | `#22c55e` | Success, positive | | Red | `#ef4444` | Errors, negative | | Purple | `#8b5cf6` | Accents, special | | Pink | `#ec4899` | Decorative | | Cyan | `#06b6d4` | Info, secondary | ### Fill Colors (pastel, for shape backgrounds) | Color | Hex | Good For | |-------|-----|----------| | Light Blue | `#a5d8ff` | Input, sources, primary | | Light Green | `#b2f2bb` | Success, output | | Light Orange | `#ffd8a8` | Warning, pending | | Light Purple | `#d0bfff` | Processing, middleware | | Light Red | `#ffc9c9` | Error, critical | | Light Yellow | `#fff3bf` | Notes, decisions | | Light Teal | `#c3fae8` | Storage, data | ## Element Types ### Required Fields (all elements) `type`, `id` (unique string), `x`, `y`, `width`, `height` ### Defaults (skip these) strokeColor="#1e1e1e", backgroundColor="transparent", fillStyle="solid", strokeWidth=2, roughness=1, opacity=100 ### Shapes **Rectangle**: `{ "type": "rectangle", "id": "r1", "x": 100, "y": 100, "width": 200, "height": 100 }` - `roundness: { type: 3 }` for rounded corners - `backgroundColor: "#a5d8ff"`, `fillStyle: "solid"` for filled **Ellipse**: `{ "type": "ellipse", "id": "e1", "x": 100, "y": 100, "width": 150, "height": 150 }` **Diamond**: `{ "type": "diamond", "id": "d1", "x": 100, "y": 100, "width": 150, "height": 150 }` ### Labels **Labeled shape (preferred)**: Add `label` to any shape for auto-centered text. ```json { "type": "rectangle", "id": "r1", "x": 100, "y": 100, "width": 200, "height": 80, "label": { "text": "Hello", "fontSize": 20 } } ``` **Standalone text** (titles, annotations only): ```json { "type": "text", "id": "t1", "x": 150, "y": 138, "text": "Hello", "fontSize": 20 } ``` ### Arrows ```json { "type": "arrow", "id": "a1", "x": 300, "y": 150, "width": 200, "height": 0, "points": [[0,0],[200,0]], "endArrowhead": "arrow" } ``` **Bindings** connect arrows to shapes: ```json "startBinding": { "elementId": "r1", "fixedPoint": [1, 0.5] } ``` fixedPoint: top=[0.5,0], bottom=[0.5,1], left=[0,0.5], right=[1,0.5] **Labeled arrow**: `"label": { "text": "connects" }` ### Camera (MCP only, not exported to PNG) ```json { "type": "cameraUpdate", "width": 800, "height": 600, "x": 0, "y": 0 } ``` Camera sizes must be 4:3 ratio. The export script filters these out automatically. ## Sizing Rules ### Container-to-text ratios - Box width >= estimated_text_width * 1.4 (40% horizontal margin) - Box height >= estimated_text_height * 1.5 (50% vertical margin) - Minimum box size: 150x60 for single-line labels, 200x80 for multi-line ### Font size constraints - Labels inside containers: max fontSize 14 - Service/zone titles: fontSize 18-22 - Standalone annotations: fontSize 12-14 - Never exceed fontSize 16 inside a box smaller than 300px wide ### Padding - Minimum 15px padding on each side between text and container edge - For multi-line text, add 8px vertical padding per line beyond the first ### General - Leave 20-30px gaps between elements ## Label Content Guidelines ### Keep labels short - Maximum 2 lines per label inside shapes - Maximum 25 characters per line - If label needs 3+ lines, split: short name in box, details as annotation below ### Label patterns - Service box: "Service Name" (1 line) or "Service Name\nBrief role" (2 lines) - Component box: "Component Name" (1 line) - Detail text: Use standalone text elements positioned below/beside the box ### Bad vs Good BAD: label "Auth-MS\nOAuth tokens, credentials\n800-1K req/s, <100ms" (3 lines, 30+ chars) GOOD: label "Auth-MS\nOAuth token management" (2 lines, 22 chars max) + standalone text below: "800-1K req/s, <100ms p99" ## Arrow Routing Rules ### Gutter-based routing - Define horizontal and vertical gutters (20-30px gaps between service zones) - Route arrows through gutters, never over content areas - Use right-angle waypoints along zone edges ### Waypoint placement - Start/end points: attach to box edges using fixedPoint bindings - Mid-waypoints: offset 20px from nearest box edge - For crossing traffic: stagger parallel arrows by 10px ### Vertical vs horizontal preference - Prefer horizontal arrows for same-tier connections - Prefer vertical arrows for cross-tier flows (consumer -> service -> external) - Diagonal arrows only when routing around would add 3+ waypoints ### Label placement on arrows - Arrow labels should sit in empty space, not over boxes - For vertical arrows: place label to the left or right, offset 15px - For horizontal arrows: place label above, offset 10px ## Example: Two Connected Boxes ```json [ { "type": "cameraUpdate", "width": 800, "height": 600, "x": 50, "y": 50 }, { "type": "rectangle", "id": "b1", "x": 100, "y": 100, "width": 200, "height": 100, "roundness": { "type": 3 }, "backgroundColor": "#a5d8ff", "fillStyle": "solid", "label": { "text": "Start", "fontSize": 20 } }, { "type": "rectangle", "id": "b2", "x": 450, "y": 100, "width": 200, "height": 100, "roundness": { "type": 3 }, "backgroundColor": "#b2f2bb", "fillStyle": "solid", "label": { "text": "End", "fontSize": 20 } }, { "type": "arrow", "id": "a1", "x": 300, "y": 150, "width": 150, "height": 0, "points": [[0,0],[150,0]], "endArrowhead": "arrow", "startBinding": { "elementId": "b1", "fixedPoint": [1, 0.5] }, "endBinding": { "elementId": "b2", "fixedPoint": [0, 0.5] } } ] ```