JSON Canvas Skill
File Structure
A canvas file (.canvas) contains two top-level arrays following the JSON Canvas Spec 1.0:
CODEBLOCK0
- -
nodes (optional): Array of node objects - INLINECODE2 (optional): Array of edge objects connecting nodes
Common Workflows
1. Create a New Canvas
- 1. Create a
.canvas file with the base structure INLINECODE4 - Generate unique 16-character hex IDs for each node (e.g.,
"6f0ad84f44ce9c17") - Add nodes with required fields:
id, type, x, y, width, INLINECODE11 - Add edges referencing valid node IDs via
fromNode and INLINECODE13 - 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
- 1. 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
- 1. 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
- 1. Read and parse the
.canvas file as JSON - Locate the target node or edge by INLINECODE29
- 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 |
|---|
| INLINECODE30 | Yes | string | Unique 16-char hex identifier |
| INLINECODE31 |
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 |
|---|
| INLINECODE44 | Yes | string | Plain text with Markdown syntax |
CODEBLOCK1
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 |
|---|
| INLINECODE49 | Yes | string | Path to file within the system |
| INLINECODE50 |
No | string | Link to heading or block (starts with
#) |
CODEBLOCK2
Link Nodes
| Attribute | Required | Type | Description |
|---|
| INLINECODE52 | Yes | string | External URL |
CODEBLOCK3
Group Nodes
Groups are visual containers for organizing other nodes. Position child nodes inside the group's bounds.
| Attribute | Required | Type | Description |
|---|
| INLINECODE53 | No | string | Text label for the group |
| INLINECODE54 |
No | string | Path to background image |
|
backgroundStyle | No | string |
cover,
ratio, or
repeat |
CODEBLOCK4
Edges
Edges connect nodes via fromNode and toNode IDs.
| Attribute | Required | Type | Default | Description |
|---|
| INLINECODE61 | Yes | string | - | Unique identifier |
| INLINECODE62 |
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 |
CODEBLOCK5
Colors
The canvasColor type accepts either a hex string or a preset number:
| Preset | Color |
|---|
| INLINECODE85 | Red |
| INLINECODE86 |
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):
CODEBLOCK6
Layout Guidelines
- - Coordinates can be negative (canvas extends infinitely)
- INLINECODE91 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:
- 1. 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) - INLINECODE99 is one of:
text, file, link, INLINECODE103 - INLINECODE104 /
toSide values are one of: top, right, bottom, INLINECODE109 - INLINECODE110 /
toEnd values are one of: none, INLINECODE113 - 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
JSON Canvas 技能
文件结构
画布文件(.canvas)包含两个遵循 JSON Canvas 规范 1.0 的顶级数组:
json
{
nodes: [],
edges: []
}
- - nodes(可选):节点对象数组
- edges(可选):连接节点的边对象数组
常见工作流程
1. 创建新画布
- 1. 创建包含基础结构 {nodes: [], edges: []} 的 .canvas 文件
- 为每个节点生成唯一的16字符十六进制ID(例如 6f0ad84f44ce9c17)
- 添加包含必填字段的节点:id、type、x、y、width、height
- 通过 fromNode 和 toNode 添加引用有效节点ID的边
- 验证:解析JSON以确认其有效性。验证所有 fromNode/toNode 值都存在于节点数组中
2. 向现有画布添加节点
- 1. 读取并解析现有的 .canvas 文件
- 生成不与现有节点或边ID冲突的唯一ID
- 选择避免与现有节点重叠的位置(x、y)(保留50-100px间距)
- 将新节点对象追加到 nodes 数组
- 可选地添加连接新节点与现有节点的边
- 验证:确认所有ID唯一且所有边引用都解析到现有节点
3. 连接两个节点
- 1. 确定源节点和目标节点ID
- 生成唯一的边ID
- 将 fromNode 和 toNode 设置为源ID和目标ID
- 可选地设置 fromSide/toSide(上、右、下、左)作为锚点
- 可选地设置 label 作为边上的描述文本
- 将边追加到 edges 数组
- 验证:确认 fromNode 和 toNode 都引用现有节点ID
4. 编辑现有画布
- 1. 以JSON格式读取并解析 .canvas 文件
- 通过 id 定位目标节点或边
- 修改所需属性(文本、位置、颜色等)
- 将更新后的JSON写回文件
- 验证:编辑后重新检查所有ID唯一性和边引用完整性
节点
节点是放置在画布上的对象。数组顺序决定z-index:第一个节点=底层,最后一个节点=顶层。
通用节点属性
| 属性 | 必填 | 类型 | 描述 |
|---|
| id | 是 | 字符串 | 唯一的16字符十六进制标识符 |
| type |
是 | 字符串 | text、file、link 或 group |
| x | 是 | 整数 | X位置(像素) |
| y | 是 | 整数 | Y位置(像素) |
| width | 是 | 整数 | 宽度(像素) |
| height | 是 | 整数 | 高度(像素) |
| color | 否 | canvasColor | 预设 1-6 或十六进制(例如 #FF0000) |
文本节点
| 属性 | 必填 | 类型 | 描述 |
|---|
| text | 是 | 字符串 | 包含Markdown语法的纯文本 |
json
{
id: 6f0ad84f44ce9c17,
type: text,
x: 0,
y: 0,
width: 400,
height: 200,
text: # Hello World\n\nThis is Markdown content.
}
换行陷阱:在JSON字符串中使用 \n 表示换行。不要使用字面量 \\n——Obsidian会将其渲染为字符 \ 和 n。
文件节点
| 属性 | 必填 | 类型 | 描述 |
|---|
| file | 是 | 字符串 | 系统内的文件路径 |
| subpath |
否 | 字符串 | 指向标题或块的链接(以 # 开头) |
json
{
id: a1b2c3d4e5f67890,
type: file,
x: 500,
y: 0,
width: 400,
height: 300,
file: Attachments/diagram.png
}
链接节点
json
{
id: c3d4e5f678901234,
type: link,
x: 1000,
y: 0,
width: 400,
height: 200,
url: https://obsidian.md
}
组节点
组是用于组织其他节点的视觉容器。将子节点放置在组的边界内。
| 属性 | 必填 | 类型 | 描述 |
|---|
| label | 否 | 字符串 | 组的文本标签 |
| background |
否 | 字符串 | 背景图片路径 |
| backgroundStyle | 否 | 字符串 | cover、ratio 或 repeat |
json
{
id: d4e5f6789012345a,
type: group,
x: -50,
y: -50,
width: 1000,
height: 600,
label: Project Overview,
color: 4
}
边
边通过 fromNode 和 toNode ID连接节点。
| 属性 | 必填 | 类型 | 默认值 | 描述 |
|---|
| id | 是 | 字符串 | - | 唯一标识符 |
| fromNode |
是 | 字符串 | - | 源节点ID |
| fromSide | 否 | 字符串 | - | top、right、bottom 或 left |
| fromEnd | 否 | 字符串 | none | none 或 arrow |
| toNode | 是 | 字符串 | - | 目标节点ID |
| toSide | 否 | 字符串 | - | top、right、bottom 或 left |
| toEnd | 否 | 字符串 | arrow | none 或 arrow |
| color | 否 | canvasColor | - | 线条颜色 |
| label | 否 | 字符串 | - | 文本标签 |
json
{
id: 0123456789abcdef,
fromNode: 6f0ad84f44ce9c17,
fromSide: right,
toNode: a1b2c3d4e5f67890,
toSide: left,
toEnd: arrow,
label: leads to
}
颜色
canvasColor 类型接受十六进制字符串或预设数字:
橙色 |
| 3 | 黄色 |
| 4 | 绿色 |
| 5 | 青色 |
| 6 | 紫色 |
预设颜色值有意未定义——应用程序使用自己的品牌颜色。
ID生成
生成16字符小写十六进制字符串(64位随机值):
6f0ad84f44ce9c17
a3b2c1d0e9f8a7b6
布局指南
- - 坐标可以为负数(画布无限延伸)
- x 向右增加,y 向下增加;位置为左上角
- 节点间距50-100px;组内保留20-50px内边距
- 对齐网格(10或20的倍数)以获得更整洁的布局
| 节点类型 | 建议宽度 | 建议高度 |
|---|
| 小文本 | 200-300 | 80-150 |
| 中文本 |
300-450