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 |
|
|
|
1---2name: json-canvas3description: Create and edit JSON Canvas files (.canvas) with nodes, edges, groups, and connections. Use when working with .canvas files, creating visual canvases, mind maps, flowcharts, or when the user mentions4---567# JSON Canvas Skill89## When to Use10- Use when creating or editing `.canvas` files for Obsidian.11- Use for mind maps, flowcharts, visual note structures, or connected canvases.12- Use when the user explicitly mentions JSON Canvas or Obsidian Canvas files.1314## File Structure1516A canvas file (`.canvas`) contains two top-level arrays following the [JSON Canvas Spec 1.0](https://jsoncanvas.org/spec/1.0/):1718```json19{20 "nodes": [],21 "edges": []22}23```2425- `nodes` (optional): Array of node objects26- `edges` (optional): Array of edge objects connecting nodes2728## Common Workflows2930### 1. Create a New Canvas31321. Create a `.canvas` file with the base structure `{"nodes": [], "edges": []}`332. Generate unique 16-character hex IDs for each node (e.g., `"6f0ad84f44ce9c17"`)343. Add nodes with required fields: `id`, `type`, `x`, `y`, `width`, `height`354. Add edges referencing valid node IDs via `fromNode` and `toNode`365. **Validate**: Parse the JSON to confirm it is valid. Verify all `fromNode`/`toNode` values exist in the nodes array3738### 2. Add a Node to an Existing Canvas39401. Read and parse the existing `.canvas` file412. Generate a unique ID that does not collide with existing node or edge IDs423. Choose position (`x`, `y`) that avoids overlapping existing nodes (leave 50-100px spacing)434. Append the new node object to the `nodes` array445. Optionally add edges connecting the new node to existing nodes456. **Validate**: Confirm all IDs are unique and all edge references resolve to existing nodes4647### 3. Connect Two Nodes48491. Identify the source and target node IDs502. Generate a unique edge ID513. Set `fromNode` and `toNode` to the source and target IDs524. Optionally set `fromSide`/`toSide` (top, right, bottom, left) for anchor points535. Optionally set `label` for descriptive text on the edge546. Append the edge to the `edges` array557. **Validate**: Confirm both `fromNode` and `toNode` reference existing node IDs5657### 4. Edit an Existing Canvas58591. Read and parse the `.canvas` file as JSON602. Locate the target node or edge by `id`613. Modify the desired attributes (text, position, color, etc.)624. Write the updated JSON back to the file635. **Validate**: Re-check all ID uniqueness and edge reference integrity after editing6465## Nodes6667Nodes are objects placed on the canvas. Array order determines z-index: first node = bottom layer, last node = top layer.6869### Generic Node Attributes7071| Attribute | Required | Type | Description |72|-----------|----------|------|-------------|73| `id` | Yes | string | Unique 16-char hex identifier |74| `type` | Yes | string | `text`, `file`, `link`, or `group` |75| `x` | Yes | integer | X position in pixels |76| `y` | Yes | integer | Y position in pixels |77| `width` | Yes | integer | Width in pixels |78| `height` | Yes | integer | Height in pixels |79| `color` | No | canvasColor | Preset `"1"`-`"6"` or hex (e.g., `"#FF0000"`) |8081### Text Nodes8283| Attribute | Required | Type | Description |84|-----------|----------|------|-------------|85| `text` | Yes | string | Plain text with Markdown syntax |8687```json88{89 "id": "6f0ad84f44ce9c17",90 "type": "text",91 "x": 0,92 "y": 0,93 "width": 400,94 "height": 200,95 "text": "# Hello World\n\nThis is **Markdown** content."96}97```9899**Newline pitfall**: Use `\n` for line breaks in JSON strings. Do **not** use the literal `\\n` -- Obsidian renders that as the characters `\` and `n`.100101### File Nodes102103| Attribute | Required | Type | Description |104|-----------|----------|------|-------------|105| `file` | Yes | string | Path to file within the system |106| `subpath` | No | string | Link to heading or block (starts with `#`) |107108```json109{110 "id": "a1b2c3d4e5f67890",111 "type": "file",112 "x": 500,113 "y": 0,114 "width": 400,115 "height": 300,116 "file": "Attachments/diagram.png"117}118```119120### Link Nodes121122| Attribute | Required | Type | Description |123|-----------|----------|------|-------------|124| `url` | Yes | string | External URL |125126```json127{128 "id": "c3d4e5f678901234",129 "type": "link",130 "x": 1000,131 "y": 0,132 "width": 400,133 "height": 200,134 "url": "https://obsidian.md"135}136```137138### Group Nodes139140Groups are visual containers for organizing other nodes. Position child nodes inside the group's bounds.141142| Attribute | Required | Type | Description |143|-----------|----------|------|-------------|144| `label` | No | string | Text label for the group |145| `background` | No | string | Path to background image |146| `backgroundStyle` | No | string | `cover`, `ratio`, or `repeat` |147148```json149{150 "id": "d4e5f6789012345a",151 "type": "group",152 "x": -50,153 "y": -50,154 "width": 1000,155 "height": 600,156 "label": "Project Overview",157 "color": "4"158}159```160161## Edges162163Edges connect nodes via `fromNode` and `toNode` IDs.164165| Attribute | Required | Type | Default | Description |166|-----------|----------|------|---------|-------------|167| `id` | Yes | string | - | Unique identifier |168| `fromNode` | Yes | string | - | Source node ID |169| `fromSide` | No | string | - | `top`, `right`, `bottom`, or `left` |170| `fromEnd` | No |