JSON Canvas
3 min read

Open file format for infinite canvas data, created by Obsidian and released under MIT. Uses .canvas extension with standard JSON encoding.

Top-level Structure

json
{
"nodes": [ ... ],
"edges": [ ... ]
}

Both arrays are optional and default to empty.

Nodes

All nodes share a common base:

FieldTypeRequiredDescription
idstringyesUnique within the file
typestringyestext, file, link, or group
xnumberyesX position (canvas coordinates)
ynumberyesY position (canvas coordinates)
widthnumberyesWidth in pixels
heightnumberyesHeight in pixels
colorstringnoPreset name or hex #rrggbb

Text Node

Markdown content embedded directly.

json
{
"id": "abc1",
"type": "text",
"x": 0, "y": 0, "width": 300, "height": 200,
"text": "## Hello\nSome **markdown** content."
}

File Node

References a file by path (relative to the vault/project root).

json
{
"id": "abc2",
"type": "file",
"x": 400, "y": 0, "width": 400, "height": 300,
"file": "notes/project.md",
"subpath": "#Section"
}

• file — relative path to the file
• subpath — optional anchor (#heading) or block reference (^blockid)


Embeds a URL (typically rendered as a web preview).

json
{
"id": "abc3",
"type": "link",
"x": 0, "y": 300, "width": 500, "height": 300,
"url": "https://example.com"
}

Group Node

Visual container for organizing other nodes. Does not affect node ownership — nodes are not logically "inside" a group; the group is purely cosmetic.

json
{
"id": "abc4",
"type": "group",
"x": -50, "y": -50, "width": 800, "height": 600,
"label": "Project Overview",
"background": "images/bg.png",
"backgroundStyle": "cover"
}

• label — displayed title for the group
• background — path or URL to a background image
• backgroundStyle — cover, ratio, or repeat

Edges

Edges connect two nodes with an optional directional arrow.

json
{
"id": "edge1",
"fromNode": "abc1",
"fromSide": "right",
"fromEnd": "none",
"toNode": "abc2",
"toSide": "left",
"toEnd": "arrow",
"color": "1",
"label": "relates to"
}

FieldTypeRequiredValues
idstringyesUnique within file
fromNodestringyesSource node id
toNodestringyesTarget node id
fromSidestringnotop, right, bottom, left
toSidestringnotop, right, bottom, left
fromEndstringnonone (default) or arrow
toEndstringnonone or arrow (default)
colorstringnoPreset or hex
labelstringnoText label shown on the edge

Colors

Preset color names map to theme-aware values in supporting apps:

ValueMeaning
"1"Red
"2"Orange
"3"Yellow
"4"Green
"5"Cyan
"6"Purple

Custom colors use hex strings: "#ff5722".

Coordinate System

• Origin (0, 0) is arbitrary — the canvas is infinite in all directions.
• x increases rightward, y increases downward.
• Node position refers to the top-left corner.

Compatible Applications

• Obsidian — origin app, full read/write support via native canvas view
• Heptabase — partial support
• Logseq — import support
• Miro — export to JSON Canvas
• Various open-source viewers and converters on GitHub

Tooling

bash
# Validate a .canvas file (Node.js library)
npm install jsoncanvas

The jsoncanvas npm package provides a parser, validator, and typed builder API.

Example — Minimal Canvas

json
{
"nodes": [
{
"id": "n1", "type": "text",
"x": 0, "y": 0, "width": 200, "height": 100,
"text": "Start"
},
{
"id": "n2", "type": "text",
"x": 300, "y": 0, "width": 200, "height": 100,
"text": "End"
}
],
"edges": [
{
"id": "e1",
"fromNode": "n1", "toNode": "n2",
"toEnd": "arrow", "label": "leads to"
}
]
}

Spec: https://jsoncanvas.org/spec/1.0/