
Json Canvas
Generate and edit Obsidian JSON Canvas (.canvas) mind maps, flowcharts, and linked visual boards without hand-writing spec-compliant node and edge JSON.
Overview
json-canvas is an agent skill most often used in Build (also Idea, Validate) that creates and edits Obsidian-compliant JSON Canvas files with validated nodes and edges.
Install
npx skills add https://github.com/kepano/obsidian-skills --skill json-canvasWhat is this skill?
- Implements JSON Canvas Spec 1.0 with nodes, edges, and optional groups
- Workflows for new canvases, adding nodes, and wiring edges with 16-char hex IDs
- Validation steps: parse JSON, unique IDs, and fromNode/toNode integrity
- Spacing guidance (50–100px) to avoid overlapping nodes when extending boards
- Supports text, file, link, and group node types per spec-driven edits
- 16-character hex node IDs
- 50–100px spacing between nodes
Adoption & trust: 30.1k installs on skills.sh; 34.9k GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
You need an Obsidian canvas or flowchart but hand-rolling .canvas JSON breaks spec rules or leaves dangling edge references.
Who is it for?
Solo builders using Obsidian who want agent-generated mind maps, architecture sketches, or linked visual boards in vault-native format.
Skip if: Teams that do not use Obsidian, or workflows that only need generic Mermaid/HTML diagrams with no .canvas requirement.
When should I use this skill?
Working with .canvas files, creating visual canvases, mind maps, flowcharts, or when the user mentions Canvas files in Obsidian.
What do I get? / Deliverables
You get a parse-valid .canvas file with unique node IDs, positioned nodes, and edges that reference real endpoints—ready to open in Obsidian.
- .canvas file with validated nodes and edges
- Updated canvas after incremental node/edge additions
Recommended Skills
Journey fit
Spans multiple journey phases - primary shelf plus alternate fits below.
Visual canvases are most often produced while documenting systems, plans, and knowledge graphs during active product work. Docs subphase is where solo builders turn ideas into shareable diagrams, vault-linked boards, and structured visual references in Obsidian.
Where it fits
Map competitor features and sources on a canvas before choosing what to build.
Lay out user journeys and MVP boundaries as linked nodes for a scope review.
Document service architecture and vault-linked file nodes for onboarding.
Maintain a living roadmap board with edges between epics and dependencies.
How it compares
Use for vault-native JSON Canvas files, not generic whiteboard PNGs or unstructured JSON blobs.
Common Questions / FAQ
Who is json-canvas for?
Indie builders and note-heavy founders who store plans in Obsidian and want agents to produce spec-valid Canvas files they can edit and sync.
When should I use json-canvas?
During idea research for competitor maps, validate scoping for feature flowcharts, and build docs for system diagrams—whenever the deliverable must be a .canvas file in Obsidian.
Is json-canvas safe to install?
It is documentation-format guidance with filesystem edits to .canvas files; review the Security Audits panel on this page before trusting it in a synced vault.
SKILL.md
READMESKILL.md - Json Canvas
# JSON Canvas Skill ## File Structure A canvas file (`.canvas`) contains two top-level arrays following the [JSON Canvas Spec 1.0](https://jsoncanvas.org/spec/1.0/): ```json { "nodes": [], "edges": [] } ``` - `nodes` (optional): Array of node objects - `edges` (optional): Array of edge objects connecting nodes ## Common Workflows ### 1. Create a New Canvas 1. Create a `.canvas` file with the base structure `{"nodes": [], "edges": []}` 2. Generate unique 16-character hex IDs for each node (e.g., `"6f0ad84f44ce9c17"`) 3. Add nodes with required fields: `id`, `type`, `x`, `y`, `width`, `height` 4. Add edges referencing valid node IDs via `fromNode` and `toNode` 5. **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 2. Generate a unique ID that does not collide with existing node or edge IDs 3. Choose position (`x`, `y`) that avoids overlapping existing nodes (leave 50-100px spacing) 4. Append the new node object to the `nodes` array 5. Optionally add edges connecting the new node to existing nodes 6. **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 2. Generate a unique edge ID 3. Set `fromNode` and `toNode` to the source and target IDs 4. Optionally set `fromSide`/`toSide` (top, right, bottom, left) for anchor points 5. Optionally set `label` for descriptive text on the edge 6. Append the edge to the `edges` array 7. **Validate**: Confirm both `fromNode` and `toNode` reference existing node IDs ### 4. Edit an Existing Canvas 1. Read and parse the `.canvas` file as JSON 2. Locate the target node or edge by `id` 3. Modify the desired attributes (text, position, color, etc.) 4. Write the updated JSON back to the file 5. **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 | ```json { "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 `#`) | ```json { "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 | ```json { "id": "c3d4e5f678901234", "type":