JSON Canvas Skill
When to Use
- Use when creating or editing
.canvas files for Obsidian.
- Use for mind maps, flowcharts, visual note structures, or connected canvases.
- Use when the user explicitly mentions JSON Canvas or Obsidian Canvas files.
File Structure
A canvas file (.canvas) contains two top-level arrays following the JSON Canvas Spec 1.0:
{
"nodes": [],
"edges": []
}
nodes (optional): Array of node objects
edges (optional): Array of edge objects connecting nodes
Common Workflows
1. Create a New Canvas
- Create a
.canvas file with the base structure {"nodes": [], "edges": []}
- Generate unique 16-character hex IDs for each node (e.g.,
"6f0ad84f44ce9c17")
- Add nodes with required fields:
id, type, x, y, width, height
- Add edges referencing valid node IDs via
fromNode and toNode
- Validate: Parse the JSON to confirm it is valid. Verify all
fromNode/toNode values exist in the nodes array
2. Add a Node to an Existing Canvas
- Read and parse the existing
.canvas file
- Generate a unique ID that does not collide with existing node or edge IDs
- Choose position (
x, y) that avoids overlapping existing nodes (leave 50-100px spacing)
- Append the new node object to the
nodes array
- Optionally add edges connecting the new node to existing nodes
- Validate: Confirm all IDs are unique and all edge references resolve to existing nodes
3. Connect Two Nodes
- Identify the source and target node IDs
- Generate a unique edge ID
- Set
fromNode and toNode to the source and target IDs
- Optionally set
fromSide/toSide (top, right, bottom, left) for anchor points
- Optionally set
label for descriptive text on the edge
- Append the edge to the
edges array
- Validate: Confirm both
fromNode and toNode reference existing node IDs
4. Edit an Existing Canvas
- Read and parse the
.canvas file as JSON
- Locate the target node or edge by
id
- Modify the desired attributes (text, position, color, etc.)
- Write the updated JSON back to the file
- Validate: Re-check all ID uniqueness and edge reference integrity after editing
Nodes
Nodes are objects placed on the canvas. Array order determines z-index: first node = bottom layer, last node = top layer.
Generic Node Attributes
| Attribute |
Required |
Type |
Description |
id |
Yes |
string |
Unique 16-char hex identifier |
type |
Yes |
string |
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 |
Preset "1"-"6" or hex (e.g., "#FF0000") |
Text Nodes
| Attribute |
Required |
Type |
Description |
text |
Yes |
string |
Plain text with Markdown syntax |
{
"id": "6f0ad84f44ce9c17",
"type": "text",
"x": 0,
"y": 0,
"width": 400,
"height": 200,
"text": "# Hello World\n\nThis is **Markdown** content."
}
Newline pitfall: Use \n for line breaks in JSON strings. Do not use the literal \\n -- Obsidian renders that as the characters \ and n.
File Nodes
| Attribute |
Required |
Type |
Description |
file |
Yes |
string |
Path to file within the system |
subpath |
No |
string |
Link to heading or block (starts with #) |
{
"id": "a1b2c3d4e5f67890",
"type": "file",
"x": 500,
"y": 0,
"width": 400,
"height": 300,
"file": "Attachments/diagram.png"
}
Link Nodes
| Attribute |
Required |
Type |
Description |
url |
Yes |
string |
External URL |
{
"id": "c3d4e5f678901234",
"type": "link",
"x": 1000,
"y": 0,
"width": 400,
"height": 200,
"url": "https://obsidian.md"
}
Group Nodes
Groups are visual containers for organizing other nodes. Position child nodes inside the group's bounds.
| Attribute |
Required |
Type |
Description |
label |
No |
string |
Text label for the group |
background |
No |
string |
Path to background image |
backgroundStyle |
No |
string |
cover, ratio, or repeat |
{
"id": "d4e5f6789012345a",
"type": "group",
"x": -50,
"y": -50,
"width": 1000,
"height": 600,
"label": "Project Overview",
"color": "4"
}
Edges
Edges connect nodes via fromNode and toNode IDs.
| Attribute |
Required |
Type |
Default |
Description |
id |
Yes |
string |
- |
Unique identifier |
fromNode |
Yes |
string |
- |
Source node ID |
fromSide |
No |
string |
- |
top, right, bottom, or left |
fromEnd |
No |
string |
none |
none or arrow |
toNode |
Yes |
string |
- |
Target node ID |
toSide |
No |
string |
- |
top, right, bottom, or left |
toEnd |
No |
string |
arrow |
none or arrow |
color |
No |
canvasColor |
- |
Line color |
label |
No |
string |
- |
Text label |
{
"id": "0123456789abcdef",
"fromNode": "6f0ad84f44ce9c17",
"fromSide": "right",
"toNode": "a1b2c3d4e5f67890",
"toSide": "left",
"toEnd": "arrow",
"label": "leads to"
}
Colors
The canvasColor type accepts either a hex string or a preset number:
| Preset |
Color |
"1" |
Red |
"2" |
Orange |
"3" |
Yellow |
"4" |
Green |
"5" |
Cyan |
"6" |
Purple |
Preset color values are intentionally undefined -- applications use their own brand colors.
ID Generation
Generate 16-character lowercase hexadecimal strings (64-bit random value):
"6f0ad84f44ce9c17"
"a3b2c1d0e9f8a7b6"
Layout Guidelines
- Coordinates can be negative (canvas extends infinitely)
x increases right, y increases down; position is the top-left corner
- Space nodes 50-100px apart; leave 20-50px padding inside groups
- Align to grid (multiples of 10 or 20) for cleaner layouts
| 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 |
Validation Checklist
After creating or editing a canvas file, verify:
- All
id values are unique across both nodes and edges
- Every
fromNode and toNode references an existing node ID
- Required fields are present for each node type (
text for text nodes, file for file nodes, url for link nodes)
type is one of: text, file, link, group
fromSide/toSide values are one of: top, right, bottom, left
fromEnd/toEnd values are one of: none, arrow
- Color presets are
"1" through "6" or valid hex (e.g., "#FF0000")
- JSON is valid and parseable
If validation fails, check for duplicate IDs, dangling edge references, or malformed JSON strings (especially unescaped newlines in text content).
Complete Examples
See references/EXAMPLES.md for full canvas examples including mind maps, project boards, research canvases, and flowcharts.
References
Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.
1---2name: json-canvas3description: Create and edit JSON Canvas files (.canvas) with nodes, edges, groups, and connections for Obsidian mind maps, flowcharts, and visual note structures.4---56# JSON Canvas Skill78## When to Use9- Use when creating or editing `.canvas` files for Obsidian.10- Use for mind maps, flowcharts, visual note structures, or connected canvases.11- Use when the user explicitly mentions JSON Canvas or Obsidian Canvas files.1213## File Structure1415A canvas file (`.canvas`) contains two top-level arrays following the [JSON Canvas Spec 1.0](https://jsoncanvas.org/spec/1.0/):1617```json18{19 "nodes": [],20 "edges": []21}22```2324- `nodes` (optional): Array of node objects25- `edges` (optional): Array of edge objects connecting nodes2627## Common Workflows2829### 1. Create a New Canvas30311. Create a `.canvas` file with the base structure `{"nodes": [], "edges": []}`322. Generate unique 16-character hex IDs for each node (e.g., `"6f0ad84f44ce9c17"`)333. Add nodes with required fields: `id`, `type`, `x`, `y`, `width`, `height`344. Add edges referencing valid node IDs via `fromNode` and `toNode`355. **Validate**: Parse the JSON to confirm it is valid. Verify all `fromNode`/`toNode` values exist in the nodes array3637### 2. Add a Node to an Existing Canvas38391. Read and parse the existing `.canvas` file402. Generate a unique ID that does not collide with existing node or edge IDs413. Choose position (`x`, `y`) that avoids overlapping existing nodes (leave 50-100px spacing)424. Append the new node object to the `nodes` array435. Optionally add edges connecting the new node to existing nodes446. **Validate**: Confirm all IDs are unique and all edge references resolve to existing nodes4546### 3. Connect Two Nodes47481. Identify the source and target node IDs492. Generate a unique edge ID503. Set `fromNode` and `toNode` to the source and target IDs514. Optionally set `fromSide`/`toSide` (top, right, bottom, left) for anchor points525. Optionally set `label` for descriptive text on the edge536. Append the edge to the `edges` array547. **Validate**: Confirm both `fromNode` and `toNode` reference existing node IDs5556### 4. Edit an Existing Canvas57581. Read and parse the `.canvas` file as JSON592. Locate the target node or edge by `id`603. Modify the desired attributes (text, position, color, etc.)614. Write the updated JSON back to the file625. **Validate**: Re-check all ID uniqueness and edge reference integrity after editing6364## Nodes6566Nodes are objects placed on the canvas. Array order determines z-index: first node = bottom layer, last node = top layer.6768### Generic Node Attributes6970| Attribute | Required | Type | Description |71|-----------|----------|------|-------------|72| `id` | Yes | string | Unique 16-char hex identifier |73| `type` | Yes | string | `text`, `file`, `link`, or `group` |74| `x` | Yes | integer | X position in pixels |75| `y` | Yes | integer | Y position in pixels |76| `width` | Yes | integer | Width in pixels |77| `height` | Yes | integer | Height in pixels |78| `color` | No | canvasColor | Preset `"1"`-`"6"` or hex (e.g., `"#FF0000"`) |7980### Text Nodes8182| Attribute | Required | Type | Description |83|-----------|----------|------|-------------|84| `text` | Yes | string | Plain text with Markdown syntax |8586```json87{88 "id": "6f0ad84f44ce9c17",89 "type": "text",90 "x": 0,91 "y": 0,92 "width": 400,93 "height": 200,94 "text": "# Hello World\n\nThis is **Markdown** content."95}96```9798**Newline pitfall**: Use `\n` for line breaks in JSON strings. Do **not** use the literal `\\n` -- Obsidian renders that as the characters `\` and `n`.99100### File Nodes101102| Attribute | Required | Type | Description |103|-----------|----------|------|-------------|104| `file` | Yes | string | Path to file within the system |105| `subpath` | No | string | Link to heading or block (starts with `#`) |106107```json108{109 "id": "a1b2c3d4e5f67890",110 "type": "file",111 "x": 500,112 "y": 0,113 "width": 400,114 "height": 300,115 "file": "Attachments/diagram.png"116}117```118119### Link Nodes120121| Attribute | Required | Type | Description |122|-----------|----------|------|-------------|123| `url` | Yes | string | External URL |124125```json126{127 "id": "c3d4e5f678901234",128 "type": "link",129 "x": 1000,130 "y": 0,131 "width": 400,132 "height": 200,133 "url": "https://obsidian.md"134}135```136137### Group Nodes138139Groups are visual containers for organizing other nodes. Position child nodes inside the group's bounds.140141| Attribute | Required | Type | Description |142|-----------|----------|------|-------------|143| `label` | No | string | Text label for the group |144| `background` | No | string | Path to background image |145| `backgroundStyle` | No | string | `cover`, `ratio`, or `repeat` |146147```json148{149 "id": "d4e5f6789012345a",150 "type": "group",151 "x": -50,152 "y": -50,153 "width": 1000,154 "height": 600,155 "label": "Project Overview",156 "color": "4"157}158```159160## Edges161162Edges connect nodes via `fromNode` and `toNode` IDs.163164| Attribute | Required | Type | Default | Description |165|-----------|----------|------|---------|-------------|166| `id` | Yes | string | - | Unique identifier |167| `fromNode` | Yes | string | - | Source node ID |168| `fromSide` | No | string | - | `top`, `right`, `bottom`, or `left` |169| `fromEnd` | No | string | `none` | `none` or `arrow` |170| `toNode` | Yes | string | - | Target node ID |171| `toSide` | No | string | - | `top`, `right`, `bottom`, or `left` |172| `toEnd` | No | string | `arrow` | `none` or `arrow` |173| `color` | No | canvasColor | - | Line color |174| `label` | No | string | - | Text label |175176```json177{178 "id": "0123456789abcdef",179 "fromNode": "6f0ad84f44ce9c17",180 "fromSide": "right",181 "toNode": "a1b2c3d4e5f67890",182 "toSide": "left",183 "toEnd": "arrow",184 "label": "leads to"185}186```187188## Colors189190The `canvasColor` type accepts either a hex string or a preset number:191192| Preset | Color |193|--------|-------|194| `"1"` | Red |195| `"2"` | Orange |196| `"3"` | Yellow |197| `"4"` | Green |198| `"5"` | Cyan |199| `"6"` | Purple |200201Preset color values are intentionally undefined -- applications use their own brand colors.202203## ID Generation204205Generate 16-character lowercase hexadecimal strings (64-bit random value):206207```208"6f0ad84f44ce9c17"209"a3b2c1d0e9f8a7b6"210```211212## Layout Guidelines213214- Coordinates can be negative (canvas extends infinitely)215- `x` increases right, `y` increases down; position is the top-left corner216- Space nodes 50-100px apart; leave 20-50px padding inside groups217- Align to grid (multiples of 10 or 20) for cleaner layouts218219| Node Type | Suggested Width | Suggested Height |220|-----------|-----------------|------------------|221| Small text | 200-300 | 80-150 |222| Medium text | 300-450 | 150-300 |223| Large text | 400-600 | 300-500 |224| File preview | 300-500 | 200-400 |225| Link preview | 250-400 | 100-200 |226227## Validation Checklist228229After creating or editing a canvas file, verify:2302311. All `id` values are unique across both nodes and edges2322. Every `fromNode` and `toNode` references an existing node ID2333. Required fields are present for each node type (`text` for text nodes, `file` for file nodes, `url` for link nodes)2344. `type` is one of: `text`, `file`, `link`, `group`2355. `fromSide`/`toSide` values are one of: `top`, `right`, `bottom`, `left`2366. `fromEnd`/`toEnd` values are one of: `none`, `arrow`2377. Color presets are `"1"` through `"6"` or valid hex (e.g., `"#FF0000"`)2388. JSON is valid and parseable239240If validation fails, check for duplicate IDs, dangling edge references, or malformed JSON strings (especially unescaped newlines in text content).241242## Complete Examples243244See [references/EXAMPLES.md](references/EXAMPLES.md) for full canvas examples including mind maps, project boards, research canvases, and flowcharts.245246## References247248- [JSON Canvas Spec 1.0](https://jsoncanvas.org/spec/1.0/)249- [JSON Canvas GitHub](https://github.com/obsidianmd/jsoncanvas)250251## Limitations252- Use this skill only when the task clearly matches the scope described above.253- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.254- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.