mirror of
https://github.com/kepano/obsidian-skills.git
synced 2026-06-08 14:05:34 -07:00
JSON Canvas
This commit is contained in:
@@ -0,0 +1,638 @@
|
|||||||
|
# JSON Canvas Skill
|
||||||
|
|
||||||
|
This skill enables Claude Code to create and edit valid JSON Canvas files (`.canvas`) used in Obsidian and other applications.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
JSON Canvas is an open file format for infinite canvas data. Canvas files use the `.canvas` extension and contain valid JSON following the [JSON Canvas Spec 1.0](https://jsoncanvas.org/spec/1.0/).
|
||||||
|
|
||||||
|
## File Structure
|
||||||
|
|
||||||
|
A canvas file contains two top-level arrays:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"nodes": [],
|
||||||
|
"edges": []
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- `nodes` (optional): Array of node objects
|
||||||
|
- `edges` (optional): Array of edge objects connecting nodes
|
||||||
|
|
||||||
|
## Nodes
|
||||||
|
|
||||||
|
Nodes are objects placed on the canvas. There are four node types:
|
||||||
|
- `text` - Text content with Markdown
|
||||||
|
- `file` - Reference to files/attachments
|
||||||
|
- `link` - External URL
|
||||||
|
- `group` - Visual container for other nodes
|
||||||
|
|
||||||
|
### Z-Index Ordering
|
||||||
|
|
||||||
|
Nodes are ordered by z-index in the array:
|
||||||
|
- First node = bottom layer (displayed below others)
|
||||||
|
- Last node = top layer (displayed above others)
|
||||||
|
|
||||||
|
### Generic Node Attributes
|
||||||
|
|
||||||
|
All nodes share these attributes:
|
||||||
|
|
||||||
|
| Attribute | Required | Type | Description |
|
||||||
|
|-----------|----------|------|-------------|
|
||||||
|
| `id` | Yes | string | Unique identifier for the node |
|
||||||
|
| `type` | Yes | string | Node type: `text`, `file`, `link`, or `group` |
|
||||||
|
| `x` | Yes | integer | X position in pixels |
|
||||||
|
| `y` | Yes | integer | Y position in pixels |
|
||||||
|
| `width` | Yes | integer | Width in pixels |
|
||||||
|
| `height` | Yes | integer | Height in pixels |
|
||||||
|
| `color` | No | canvasColor | Node color (see Color section) |
|
||||||
|
|
||||||
|
### Text Nodes
|
||||||
|
|
||||||
|
Text nodes contain Markdown content.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "6f0ad84f44ce9c17",
|
||||||
|
"type": "text",
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"width": 400,
|
||||||
|
"height": 200,
|
||||||
|
"text": "# Hello World\n\nThis is **Markdown** content."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| Attribute | Required | Type | Description |
|
||||||
|
|-----------|----------|------|-------------|
|
||||||
|
| `text` | Yes | string | Plain text with Markdown syntax |
|
||||||
|
|
||||||
|
### File Nodes
|
||||||
|
|
||||||
|
File nodes reference files or attachments (images, videos, PDFs, notes, etc.).
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "a1b2c3d4e5f67890",
|
||||||
|
"type": "file",
|
||||||
|
"x": 500,
|
||||||
|
"y": 0,
|
||||||
|
"width": 400,
|
||||||
|
"height": 300,
|
||||||
|
"file": "Attachments/diagram.png"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "b2c3d4e5f6789012",
|
||||||
|
"type": "file",
|
||||||
|
"x": 500,
|
||||||
|
"y": 400,
|
||||||
|
"width": 400,
|
||||||
|
"height": 300,
|
||||||
|
"file": "Notes/Project Overview.md",
|
||||||
|
"subpath": "#Implementation"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| Attribute | Required | Type | Description |
|
||||||
|
|-----------|----------|------|-------------|
|
||||||
|
| `file` | Yes | string | Path to file within the system |
|
||||||
|
| `subpath` | No | string | Link to heading or block (starts with `#`) |
|
||||||
|
|
||||||
|
### Link Nodes
|
||||||
|
|
||||||
|
Link nodes display external URLs.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "c3d4e5f678901234",
|
||||||
|
"type": "link",
|
||||||
|
"x": 1000,
|
||||||
|
"y": 0,
|
||||||
|
"width": 400,
|
||||||
|
"height": 200,
|
||||||
|
"url": "https://obsidian.md"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| Attribute | Required | Type | Description |
|
||||||
|
|-----------|----------|------|-------------|
|
||||||
|
| `url` | Yes | string | External URL |
|
||||||
|
|
||||||
|
### Group Nodes
|
||||||
|
|
||||||
|
Group nodes are visual containers for organizing other nodes.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "d4e5f6789012345a",
|
||||||
|
"type": "group",
|
||||||
|
"x": -50,
|
||||||
|
"y": -50,
|
||||||
|
"width": 1000,
|
||||||
|
"height": 600,
|
||||||
|
"label": "Project Overview",
|
||||||
|
"color": "4"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "e5f67890123456ab",
|
||||||
|
"type": "group",
|
||||||
|
"x": 0,
|
||||||
|
"y": 700,
|
||||||
|
"width": 800,
|
||||||
|
"height": 500,
|
||||||
|
"label": "Resources",
|
||||||
|
"background": "Attachments/background.png",
|
||||||
|
"backgroundStyle": "cover"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| Attribute | Required | Type | Description |
|
||||||
|
|-----------|----------|------|-------------|
|
||||||
|
| `label` | No | string | Text label for the group |
|
||||||
|
| `background` | No | string | Path to background image |
|
||||||
|
| `backgroundStyle` | No | string | Background rendering style |
|
||||||
|
|
||||||
|
#### Background Styles
|
||||||
|
|
||||||
|
| Value | Description |
|
||||||
|
|-------|-------------|
|
||||||
|
| `cover` | Fills entire width and height of node |
|
||||||
|
| `ratio` | Maintains aspect ratio of background image |
|
||||||
|
| `repeat` | Repeats image as pattern in both directions |
|
||||||
|
|
||||||
|
## Edges
|
||||||
|
|
||||||
|
Edges are lines connecting nodes.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "f67890123456789a",
|
||||||
|
"fromNode": "6f0ad84f44ce9c17",
|
||||||
|
"toNode": "a1b2c3d4e5f67890"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "0123456789abcdef",
|
||||||
|
"fromNode": "6f0ad84f44ce9c17",
|
||||||
|
"fromSide": "right",
|
||||||
|
"fromEnd": "none",
|
||||||
|
"toNode": "b2c3d4e5f6789012",
|
||||||
|
"toSide": "left",
|
||||||
|
"toEnd": "arrow",
|
||||||
|
"color": "1",
|
||||||
|
"label": "leads to"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| Attribute | Required | Type | Default | Description |
|
||||||
|
|-----------|----------|------|---------|-------------|
|
||||||
|
| `id` | Yes | string | - | Unique identifier for the edge |
|
||||||
|
| `fromNode` | Yes | string | - | Node ID where connection starts |
|
||||||
|
| `fromSide` | No | string | - | Side where edge starts |
|
||||||
|
| `fromEnd` | No | string | `none` | Shape at edge start |
|
||||||
|
| `toNode` | Yes | string | - | Node ID where connection ends |
|
||||||
|
| `toSide` | No | string | - | Side where edge ends |
|
||||||
|
| `toEnd` | No | string | `arrow` | Shape at edge end |
|
||||||
|
| `color` | No | canvasColor | - | Line color |
|
||||||
|
| `label` | No | string | - | Text label for the edge |
|
||||||
|
|
||||||
|
### Side Values
|
||||||
|
|
||||||
|
| Value | Description |
|
||||||
|
|-------|-------------|
|
||||||
|
| `top` | Top edge of node |
|
||||||
|
| `right` | Right edge of node |
|
||||||
|
| `bottom` | Bottom edge of node |
|
||||||
|
| `left` | Left edge of node |
|
||||||
|
|
||||||
|
### End Shapes
|
||||||
|
|
||||||
|
| Value | Description |
|
||||||
|
|-------|-------------|
|
||||||
|
| `none` | No endpoint shape |
|
||||||
|
| `arrow` | Arrow endpoint |
|
||||||
|
|
||||||
|
## Colors
|
||||||
|
|
||||||
|
The `canvasColor` type can be specified in two ways:
|
||||||
|
|
||||||
|
### Hex Colors
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"color": "#FF0000"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Preset Colors
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"color": "1"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| Preset | Color |
|
||||||
|
|--------|-------|
|
||||||
|
| `"1"` | Red |
|
||||||
|
| `"2"` | Orange |
|
||||||
|
| `"3"` | Yellow |
|
||||||
|
| `"4"` | Green |
|
||||||
|
| `"5"` | Cyan |
|
||||||
|
| `"6"` | Purple |
|
||||||
|
|
||||||
|
Note: Specific color values for presets are intentionally undefined, allowing applications to use their own brand colors.
|
||||||
|
|
||||||
|
## Complete Examples
|
||||||
|
|
||||||
|
### Simple Canvas with Text and Connections
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"id": "8a9b0c1d2e3f4a5b",
|
||||||
|
"type": "text",
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"width": 300,
|
||||||
|
"height": 150,
|
||||||
|
"text": "# Main Idea\n\nThis is the central concept."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "1a2b3c4d5e6f7a8b",
|
||||||
|
"type": "text",
|
||||||
|
"x": 400,
|
||||||
|
"y": -100,
|
||||||
|
"width": 250,
|
||||||
|
"height": 100,
|
||||||
|
"text": "## Supporting Point A\n\nDetails here."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "2b3c4d5e6f7a8b9c",
|
||||||
|
"type": "text",
|
||||||
|
"x": 400,
|
||||||
|
"y": 100,
|
||||||
|
"width": 250,
|
||||||
|
"height": 100,
|
||||||
|
"text": "## Supporting Point B\n\nMore details."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"edges": [
|
||||||
|
{
|
||||||
|
"id": "3c4d5e6f7a8b9c0d",
|
||||||
|
"fromNode": "8a9b0c1d2e3f4a5b",
|
||||||
|
"fromSide": "right",
|
||||||
|
"toNode": "1a2b3c4d5e6f7a8b",
|
||||||
|
"toSide": "left"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "4d5e6f7a8b9c0d1e",
|
||||||
|
"fromNode": "8a9b0c1d2e3f4a5b",
|
||||||
|
"fromSide": "right",
|
||||||
|
"toNode": "2b3c4d5e6f7a8b9c",
|
||||||
|
"toSide": "left"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Project Board with Groups
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"id": "5e6f7a8b9c0d1e2f",
|
||||||
|
"type": "group",
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"width": 300,
|
||||||
|
"height": 500,
|
||||||
|
"label": "To Do",
|
||||||
|
"color": "1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "6f7a8b9c0d1e2f3a",
|
||||||
|
"type": "group",
|
||||||
|
"x": 350,
|
||||||
|
"y": 0,
|
||||||
|
"width": 300,
|
||||||
|
"height": 500,
|
||||||
|
"label": "In Progress",
|
||||||
|
"color": "3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "7a8b9c0d1e2f3a4b",
|
||||||
|
"type": "group",
|
||||||
|
"x": 700,
|
||||||
|
"y": 0,
|
||||||
|
"width": 300,
|
||||||
|
"height": 500,
|
||||||
|
"label": "Done",
|
||||||
|
"color": "4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "8b9c0d1e2f3a4b5c",
|
||||||
|
"type": "text",
|
||||||
|
"x": 20,
|
||||||
|
"y": 50,
|
||||||
|
"width": 260,
|
||||||
|
"height": 80,
|
||||||
|
"text": "## Task 1\n\nImplement feature X"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "9c0d1e2f3a4b5c6d",
|
||||||
|
"type": "text",
|
||||||
|
"x": 370,
|
||||||
|
"y": 50,
|
||||||
|
"width": 260,
|
||||||
|
"height": 80,
|
||||||
|
"text": "## Task 2\n\nReview PR #123",
|
||||||
|
"color": "2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "0d1e2f3a4b5c6d7e",
|
||||||
|
"type": "text",
|
||||||
|
"x": 720,
|
||||||
|
"y": 50,
|
||||||
|
"width": 260,
|
||||||
|
"height": 80,
|
||||||
|
"text": "## Task 3\n\n~~Setup CI/CD~~"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"edges": []
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Research Canvas with Files and Links
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"id": "1e2f3a4b5c6d7e8f",
|
||||||
|
"type": "text",
|
||||||
|
"x": 300,
|
||||||
|
"y": 200,
|
||||||
|
"width": 400,
|
||||||
|
"height": 200,
|
||||||
|
"text": "# Research Topic\n\n## Key Questions\n\n- How does X affect Y?\n- What are the implications?",
|
||||||
|
"color": "5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "2f3a4b5c6d7e8f9a",
|
||||||
|
"type": "file",
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"width": 250,
|
||||||
|
"height": 150,
|
||||||
|
"file": "Literature/Paper A.pdf"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3a4b5c6d7e8f9a0b",
|
||||||
|
"type": "file",
|
||||||
|
"x": 0,
|
||||||
|
"y": 200,
|
||||||
|
"width": 250,
|
||||||
|
"height": 150,
|
||||||
|
"file": "Notes/Meeting Notes.md",
|
||||||
|
"subpath": "#Key Insights"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "4b5c6d7e8f9a0b1c",
|
||||||
|
"type": "link",
|
||||||
|
"x": 0,
|
||||||
|
"y": 400,
|
||||||
|
"width": 250,
|
||||||
|
"height": 100,
|
||||||
|
"url": "https://example.com/research"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "5c6d7e8f9a0b1c2d",
|
||||||
|
"type": "file",
|
||||||
|
"x": 750,
|
||||||
|
"y": 150,
|
||||||
|
"width": 300,
|
||||||
|
"height": 250,
|
||||||
|
"file": "Attachments/diagram.png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"edges": [
|
||||||
|
{
|
||||||
|
"id": "6d7e8f9a0b1c2d3e",
|
||||||
|
"fromNode": "2f3a4b5c6d7e8f9a",
|
||||||
|
"fromSide": "right",
|
||||||
|
"toNode": "1e2f3a4b5c6d7e8f",
|
||||||
|
"toSide": "left",
|
||||||
|
"label": "supports"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "7e8f9a0b1c2d3e4f",
|
||||||
|
"fromNode": "3a4b5c6d7e8f9a0b",
|
||||||
|
"fromSide": "right",
|
||||||
|
"toNode": "1e2f3a4b5c6d7e8f",
|
||||||
|
"toSide": "left",
|
||||||
|
"label": "informs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "8f9a0b1c2d3e4f5a",
|
||||||
|
"fromNode": "4b5c6d7e8f9a0b1c",
|
||||||
|
"fromSide": "right",
|
||||||
|
"toNode": "1e2f3a4b5c6d7e8f",
|
||||||
|
"toSide": "left",
|
||||||
|
"toEnd": "arrow",
|
||||||
|
"color": "6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "9a0b1c2d3e4f5a6b",
|
||||||
|
"fromNode": "1e2f3a4b5c6d7e8f",
|
||||||
|
"fromSide": "right",
|
||||||
|
"toNode": "5c6d7e8f9a0b1c2d",
|
||||||
|
"toSide": "left",
|
||||||
|
"label": "visualized by"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Flowchart
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"id": "a0b1c2d3e4f5a6b7",
|
||||||
|
"type": "text",
|
||||||
|
"x": 200,
|
||||||
|
"y": 0,
|
||||||
|
"width": 150,
|
||||||
|
"height": 60,
|
||||||
|
"text": "**Start**",
|
||||||
|
"color": "4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "b1c2d3e4f5a6b7c8",
|
||||||
|
"type": "text",
|
||||||
|
"x": 200,
|
||||||
|
"y": 100,
|
||||||
|
"width": 150,
|
||||||
|
"height": 60,
|
||||||
|
"text": "Step 1:\nGather data"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "c2d3e4f5a6b7c8d9",
|
||||||
|
"type": "text",
|
||||||
|
"x": 200,
|
||||||
|
"y": 200,
|
||||||
|
"width": 150,
|
||||||
|
"height": 80,
|
||||||
|
"text": "**Decision**\n\nIs data valid?",
|
||||||
|
"color": "3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "d3e4f5a6b7c8d9e0",
|
||||||
|
"type": "text",
|
||||||
|
"x": 400,
|
||||||
|
"y": 200,
|
||||||
|
"width": 150,
|
||||||
|
"height": 60,
|
||||||
|
"text": "Process data"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "e4f5a6b7c8d9e0f1",
|
||||||
|
"type": "text",
|
||||||
|
"x": 0,
|
||||||
|
"y": 200,
|
||||||
|
"width": 150,
|
||||||
|
"height": 60,
|
||||||
|
"text": "Request new data",
|
||||||
|
"color": "1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "f5a6b7c8d9e0f1a2",
|
||||||
|
"type": "text",
|
||||||
|
"x": 400,
|
||||||
|
"y": 320,
|
||||||
|
"width": 150,
|
||||||
|
"height": 60,
|
||||||
|
"text": "**End**",
|
||||||
|
"color": "4"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"edges": [
|
||||||
|
{
|
||||||
|
"id": "a6b7c8d9e0f1a2b3",
|
||||||
|
"fromNode": "a0b1c2d3e4f5a6b7",
|
||||||
|
"fromSide": "bottom",
|
||||||
|
"toNode": "b1c2d3e4f5a6b7c8",
|
||||||
|
"toSide": "top"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "b7c8d9e0f1a2b3c4",
|
||||||
|
"fromNode": "b1c2d3e4f5a6b7c8",
|
||||||
|
"fromSide": "bottom",
|
||||||
|
"toNode": "c2d3e4f5a6b7c8d9",
|
||||||
|
"toSide": "top"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "c8d9e0f1a2b3c4d5",
|
||||||
|
"fromNode": "c2d3e4f5a6b7c8d9",
|
||||||
|
"fromSide": "right",
|
||||||
|
"toNode": "d3e4f5a6b7c8d9e0",
|
||||||
|
"toSide": "left",
|
||||||
|
"label": "Yes",
|
||||||
|
"color": "4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "d9e0f1a2b3c4d5e6",
|
||||||
|
"fromNode": "c2d3e4f5a6b7c8d9",
|
||||||
|
"fromSide": "left",
|
||||||
|
"toNode": "e4f5a6b7c8d9e0f1",
|
||||||
|
"toSide": "right",
|
||||||
|
"label": "No",
|
||||||
|
"color": "1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "e0f1a2b3c4d5e6f7",
|
||||||
|
"fromNode": "e4f5a6b7c8d9e0f1",
|
||||||
|
"fromSide": "top",
|
||||||
|
"fromEnd": "none",
|
||||||
|
"toNode": "b1c2d3e4f5a6b7c8",
|
||||||
|
"toSide": "left",
|
||||||
|
"toEnd": "arrow"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "f1a2b3c4d5e6f7a8",
|
||||||
|
"fromNode": "d3e4f5a6b7c8d9e0",
|
||||||
|
"fromSide": "bottom",
|
||||||
|
"toNode": "f5a6b7c8d9e0f1a2",
|
||||||
|
"toSide": "top"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## ID Generation
|
||||||
|
|
||||||
|
Node and edge IDs must be unique strings. Obsidian generates 16-character hexadecimal IDs:
|
||||||
|
|
||||||
|
```json
|
||||||
|
"id": "6f0ad84f44ce9c17"
|
||||||
|
"id": "a3b2c1d0e9f8g7h6"
|
||||||
|
"id": "1234567890abcdef"
|
||||||
|
```
|
||||||
|
|
||||||
|
This format is a 16-character lowercase hex string (64-bit random value).
|
||||||
|
|
||||||
|
## Layout Guidelines
|
||||||
|
|
||||||
|
### Positioning
|
||||||
|
|
||||||
|
- Coordinates can be negative (canvas extends infinitely)
|
||||||
|
- `x` increases to the right
|
||||||
|
- `y` increases downward
|
||||||
|
- Position refers to top-left corner of node
|
||||||
|
|
||||||
|
### Recommended Sizes
|
||||||
|
|
||||||
|
| Node Type | Suggested Width | Suggested Height |
|
||||||
|
|-----------|-----------------|------------------|
|
||||||
|
| Small text | 200-300 | 80-150 |
|
||||||
|
| Medium text | 300-450 | 150-300 |
|
||||||
|
| Large text | 400-600 | 300-500 |
|
||||||
|
| File preview | 300-500 | 200-400 |
|
||||||
|
| Link preview | 250-400 | 100-200 |
|
||||||
|
| Group | Varies | Varies |
|
||||||
|
|
||||||
|
### Spacing
|
||||||
|
|
||||||
|
- Leave 20-50px padding inside groups
|
||||||
|
- Space nodes 50-100px apart for readability
|
||||||
|
- Align nodes to grid (multiples of 10 or 20) for cleaner layouts
|
||||||
|
|
||||||
|
## Validation Rules
|
||||||
|
|
||||||
|
1. All `id` values must be unique across nodes and edges
|
||||||
|
2. `fromNode` and `toNode` must reference existing node IDs
|
||||||
|
3. Required fields must be present for each node type
|
||||||
|
4. `type` must be one of: `text`, `file`, `link`, `group`
|
||||||
|
5. `backgroundStyle` must be one of: `cover`, `ratio`, `repeat`
|
||||||
|
6. `fromSide`, `toSide` must be one of: `top`, `right`, `bottom`, `left`
|
||||||
|
7. `fromEnd`, `toEnd` must be one of: `none`, `arrow`
|
||||||
|
8. Color presets must be `"1"` through `"6"` or valid hex color
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [JSON Canvas Spec 1.0](https://jsoncanvas.org/spec/1.0/)
|
||||||
|
- [JSON Canvas GitHub](https://github.com/obsidianmd/jsoncanvas)
|
||||||
|
|
||||||
Reference in New Issue
Block a user