# JSON Canvas Specification for Obsidian Version 1.0 — 2024-03-11 ## Overview JSON Canvas is a format for representing infinite canvas documents. This specification defines the structure for creating canvas files compatible with Obsidian. ## Top Level Structure The root JSON object contains two optional arrays: ```json { "nodes": [...], "edges": [...] } ``` - `nodes` (optional, array): All canvas objects (text, files, links, groups) - `edges` (optional, array): All connections between nodes ## Node Types ### Common Attributes All nodes share these required attributes: - `id` (required, string): Unique identifier for the node - `type` (required, string): Node type (`text`, `file`, `link`, `group`) - `x` (required, integer): X position in pixels - `y` (required, integer): Y position in pixels - `width` (required, integer): Width in pixels - `height` (required, integer): Height in pixels - `color` (optional, string/number): Color (hex `"#FF0000"` or preset `"1"`) ### Text Nodes Store plain text with Markdown formatting. **Required Attributes:** - `text` (string): Content in Markdown syntax **Example:** ```json { "id": "abc123", "type": "text", "x": 0, "y": 0, "width": 250, "height": 100, "text": "# Main Topic\n\nKey point here", "color": "4" } ``` ### File Nodes Reference other files or attachments (images, PDFs, etc.). **Required Attributes:** - `file` (string): Path to file in the vault **Optional Attributes:** - `subpath` (string): Link to specific heading/block (starts with `#`) **Example:** ```json { "id": "def456", "type": "file", "x": 300, "y": 0, "width": 400, "height": 300, "file": "Images/diagram.png" } ``` **With Subpath:** ```json { "id": "ghi789", "type": "file", "x": 0, "y": 200, "width": 250, "height": 100, "file": "Notes/Meeting Notes.md", "subpath": "#Action Items" } ``` ### Link Nodes Reference external URLs. **Required Attributes:** - `url` (string): Full URL including protocol **Example:** ```json { "id": "jkl012", "type": "link", "x": 0, "y": -200, "width": 250, "height": 100, "url": "https://obsidian.md", "color": "5" } ``` ### Group Nodes Visual containers for organizing related nodes. **Optional Attributes:** - `label` (string): Text label for the group (recommended) - `background` (string): Path to background image - `backgroundStyle` (string): Image rendering style - `cover`: Fill entire node - `ratio`: Maintain aspect ratio - `repeat`: Tile as pattern **Example:** ```json { "id": "group1", "type": "group", "x": -50, "y": -50, "width": 600, "height": 400, "label": "Main Concepts", "color": "4" } ``` **With Background:** ```json { "id": "group2", "type": "group", "x": 700, "y": 0, "width": 500, "height": 600, "label": "Reference Materials", "background": "Images/texture.png", "backgroundStyle": "repeat" } ``` ## Z-Index and Layering Nodes are displayed in array order: - **First node**: Bottom layer (rendered below others) - **Last node**: Top layer (rendered above others) **Best Practice Order:** 1. Group nodes (backgrounds) 2. Sub-groups 3. Regular nodes (text, file, link) This ensures groups appear behind content. ## Edges (Connections) Edges connect nodes with lines. **Required Attributes:** - `id` (required, string): Unique identifier - `fromNode` (required, string): Starting node ID - `toNode` (required, string): Ending node ID **Optional Attributes:** - `fromSide` (string): Starting edge side - Values: `top`, `right`, `bottom`, `left` - `fromEnd` (string): Start endpoint shape - Values: `none` (default), `arrow` - `toSide` (string): Ending edge side - Values: `top`, `right`, `bottom`, `left` - `toEnd` (string): End endpoint shape - Values: `arrow` (default), `none` - `color` (string/number): Edge color - `label` (string): Text label on edge **Example - Simple Connection:** ```json { "id": "edge1", "fromNode": "abc123", "toNode": "def456" } ``` **Example - Fully Specified:** ```json { "id": "edge2", "fromNode": "def456", "fromSide": "bottom", "fromEnd": "none", "toNode": "ghi789", "toSide": "top", "toEnd": "arrow", "color": "3", "label": "leads to" } ``` ## Color System ### Preset Colors Use string numbers `"1"` through `"6"`: - `"1"` - Red - `"2"` - Orange - `"3"` - Yellow - `"4"` - Green - `"5"` - Cyan - `"6"` - Purple **Note:** Exact colors adapt to Obsidian's theme. These provide semantic meaning across light/dark modes. ### Custom Hex Colors Use hex format: `"#RRGGBB"` **Examples:** - `"#4A90E2"` (blue) - `"#50E3C2"` (teal) - `"#F5A623"` (orange) **Best Practice:** Use consistent format within a canvas (all hex OR all presets). ## Complete Example ```json { "nodes": [ { "id": "group001", "type": "group", "x": -50, "y": -50, "width": 700, "height": 500, "label": "Core Concepts", "color": "4" }, { "id": "center01", "type": "text", "x": 0, "y": 0, "width": 300, "height": 120, "text": "# Central Topic\n\nMain idea here", "color": "4" }, { "id": "branch01", "type": "text", "x": 400, "y": -100, "width": 220, "height": 100, "text": "Subtopic A", "color": "5" }, { "id": "branch02", "type": "text", "x": 400, "y": 100, "width": 220, "height": 100, "text": "Subtopic B", "color": "5" }, { "id": "detail01", "type": "text", "x": 700, "y": -100, "width": 200, "height": 80, "text": "Detail 1", "color": "6" } ], "edges": [ { "id": "e1", "fromNode": "center01", "fromSide": "right", "toNode": "branch01", "toSide": "left", "toEnd": "arrow" }, { "id": "e2", "fromNode": "center01", "fromSide": "right", "toNode": "branch02", "toSide": "left", "toEnd": "arrow" }, { "id": "e3", "fromNode": "branch01", "fromSide": "right", "toNode": "detail01", "toSide": "left", "toEnd": "arrow", "color": "3" } ] } ``` ## Validation Requirements When creating canvas files, ensure: 1. **Unique IDs**: All `id` values must be unique across nodes and edges 2. **Valid References**: All edge `fromNode` and `toNode` must reference existing node IDs 3. **Required Fields**: All required attributes are present for each type 4. **Valid Coordinates**: All position/dimension values are integers 5. **Color Format**: Colors use either hex (`"#RRGGBB"`) or preset strings (`"1"` to `"6"`) 6. **Quote Escaping**: Special characters properly escaped in JSON strings ## Common Issues and Solutions ### Issue: Canvas won't open in Obsidian **Solutions:** - Validate JSON syntax (use JSON validator) - Check all IDs are unique - Verify all edge references exist - Ensure required fields present ### Issue: Nodes appear overlapped **Solutions:** - Increase spacing between coordinates - Account for node dimensions in positioning - Use minimum spacing: 320px horizontal, 200px vertical ### Issue: Groups don't show properly **Solutions:** - Ensure groups appear before content nodes in array - Add explicit `label` to all groups - Check group dimensions encompass child nodes ### Issue: Colors don't match expectations **Solutions:** - Use consistent color format (all hex OR all presets) - Remember presets adapt to theme - Test in both light and dark mode if using custom colors ### Issue: Text appears truncated **Solutions:** - Increase node dimensions - Break long text into multiple nodes - Use file nodes for lengthy content ## Character Encoding for Chinese Content When canvas contains Chinese text, apply these transformations: - Chinese double quotes `"` → `『』` - Chinese single quotes `'` → `「」` - English double quotes must be escaped: `\"` **Example:** ```json { "text": "『核心概念』包含:「子概念A」和「子概念B」" } ``` This prevents JSON parsing errors with mixed-language content. ## Performance Considerations - **Large Canvases**: Keep node count reasonable (<500 for smooth performance) - **Image Files**: Use compressed images for backgrounds - **Text Length**: Keep node text concise; use file nodes for long content - **Edge Complexity**: Minimize crossing edges for clarity ## Future Extensions This specification may be extended with: - Additional node types - More edge styling options - Animation properties - Interactive behaviors Always check Obsidian documentation for latest Canvas features.