{"id":"json-canvas","name":"json-canvas","summary":"ノード、エッジ、グループ、接続を含むJSON Canvasファイル(.canvas)を作成・編集できます。","body":"# JSON Canvas Skill\n\nThis skill enables skills-compatible agents to create and edit valid JSON Canvas files (`.canvas`) used in Obsidian and other applications.\n\n## Overview\n\nJSON Canvas is an open file format for infinite canvas data. Canvas files use the `.canvas` extension and contain valid JSON following the [JSON Canvas Spec 1.0](https://jsoncanvas.org/spec/1.0/).\n\n## File Structure\n\nA canvas file contains two top-level arrays:\n\n```json\n{\n  \"nodes\": [],\n  \"edges\": []\n}\n```\n\n- `nodes` (optional): Array of node objects\n- `edges` (optional): Array of edge objects connecting nodes\n\n## Nodes\n\nNodes are objects placed on the canvas. There are four node types:\n- `text` - Text content with Markdown\n- `file` - Reference to files/attachments\n- `link` - External URL\n- `group` - Visual container for other nodes\n\n### Z-Index Ordering\n\nNodes are ordered by z-index in the array:\n- First node = bottom layer (displayed below others)\n- Last node = top layer (displayed above others)\n\n### Generic Node Attributes\n\nAll nodes share these attributes:\n\n| Attribute | Required | Type | Description |\n|-----------|----------|------|-------------|\n| `id` | Yes | string | Unique identifier for the node |\n| `type` | Yes | string | Node type: `text`, `file`, `link`, or `group` |\n| `x` | Yes | integer | X position in pixels |\n| `y` | Yes | integer | Y position in pixels |\n| `width` | Yes | integer | Width in pixels |\n| `height` | Yes | integer | Height in pixels |\n| `color` | No | canvasColor | Node color (see Color section) |\n\n### Text Nodes\n\nText nodes contain Markdown content.\n\n```json\n{\n  \"id\": \"6f0ad84f44ce9c17\",\n  \"type\": \"text\",\n  \"x\": 0,\n  \"y\": 0,\n  \"width\": 400,\n  \"height\": 200,\n  \"text\": \"# Hello World\\n\\nThis is **Markdown** content.\"\n}\n```\n\n#### Newline Escaping (Common Pitfall)\n\nIn JSON, newline characters inside strings **must** be represented as `\\n`. Do **not** use the literal sequence `\\\\n` in a `.canvas` file—Obsidian will render it as the characters `\\` and `n` instead of a line break.\n\nExamples:\n\n```json\n{ \"type\": \"text\", \"text\": \"Line 1\\nLine 2\" }\n```\n\n```json\n{ \"type\": \"text\", \"text\": \"Line 1\\\\nLine 2\" }\n```\n\n| Attribute | Required | Type | Description |\n|-----------|----------|------|-------------|\n| `text` | Yes | string | Plain text with Markdown syntax |\n\n### File Nodes\n\nFile nodes reference files or attachments (images, videos, PDFs, notes, etc.).\n\n```json\n{\n  \"id\": \"a1b2c3d4e5f67890\",\n  \"type\": \"file\",\n  \"x\": 500,\n  \"y\": 0,\n  \"width\": 400,\n  \"height\": 300,\n  \"file\": \"Attachments/diagram.png\"\n}\n```\n\n```json\n{\n  \"id\": \"b2c3d4e5f6789012\",\n  \"type\": \"file\",\n  \"x\": 500,\n  \"y\": 400,\n  \"width\": 400,\n  \"height\": 300,\n  \"file\": \"Notes/Project Overview.md\",\n  \"subpath\": \"#Implementation\"\n}\n```\n\n| Attribute | Required | Type | Description |\n|-----------|----------|------|-------------|\n| `file` | Yes | string | Path to file within the system |\n| `subpath` | No | string | Link to heading or block (starts with `#`) |\n\n### Link Nodes\n\nLink nodes display external URLs.\n\n```json\n{\n  \"id\": \"c3d4e5f678901234\",\n  \"type\": \"link\",\n  \"x\": 1000,\n  \"y\": 0,\n  \"width\": 400,\n  \"height\": 200,\n  \"url\": \"https://obsidian.md\"\n}\n```\n\n| Attribute | Required | Type | Description |\n|-----------|----------|------|-------------|\n| `url` | Yes | string | External URL |\n\n### Group Nodes\n\nGroup nodes are visual containers for organizing other nodes.\n\n```json\n{\n  \"id\": \"d4e5f6789012345a\",\n  \"type\": \"group\",\n  \"x\": -50,\n  \"y\": -50,\n  \"width\": 1000,\n  \"height\": 600,\n  \"label\": \"Project Overview\",\n  \"color\": \"4\"\n}\n```\n\n```json\n{\n  \"id\": \"e5f67890123456ab\",\n  \"type\": \"group\",\n  \"x\": 0,\n  \"y\": 700,\n  \"width\": 800,\n  \"height\": 500,\n  \"label\": \"Resources\",\n  \"background\": \"Attachments/background.png\",\n  \"backgroundStyle\": \"cover\"\n}\n```\n\n| Attribute | Required | Type | Description |\n|-----------|----------|------|-------------|\n| `label` | No | string | Text label for the group |\n| `background` | No | string | Path to background image |\n| `backgroundStyle` | No | string | Background rendering style |\n\n#### Background Styles\n\n| Value | Description |\n|-------|-------------|\n| `cover` | Fills entire width and height of node |\n| `ratio` | Maintains aspect ratio of background image |\n| `repeat` | Repeats image as pattern in both directions |\n\n## Edges\n\nEdges are lines connecting nodes.\n\n```json\n{\n  \"id\": \"f67890123456789a\",\n  \"fromNode\": \"6f0ad84f44ce9c17\",\n  \"toNode\": \"a1b2c3d4e5f67890\"\n}\n```\n\n```json\n{\n  \"id\": \"0123456789abcdef\",\n  \"fromNode\": \"6f0ad84f44ce9c17\",\n  \"fromSide\": \"right\",\n  \"fromEnd\": \"none\",\n  \"toNode\": \"b2c3d4e5f6789012\",\n  \"toSide\": \"left\",\n  \"toEnd\": \"arrow\",\n  \"color\": \"1\",\n  \"label\": \"leads to\"\n}\n```\n\n| Attribute | Required | Type | Default | Description |\n|-----------|----------|------|---------|-------------|\n| `id` | Yes | string | - | Unique identifier for the edge |\n| `fromNode` | Yes | string | - | Node ID where connection starts |\n| `fromSide` | No | string | - | Side where edge starts |\n| `fromEnd` | No | string | `none` | Shape at edge start |\n| `toNode` | Yes | string | - | Node ID where connection ends |\n| `toSide` | No | string | - | Side where edge ends |\n| `toEnd` | No | string | `arrow` | Shape at edge end |\n| `color` | No | canvasColor | - | Line color |\n| `label` | No | string | - | Text label for the edge |\n\n### Side Values\n\n| Value | Description |\n|-------|-------------|\n| `top` | Top edge of node |\n| `right` | Right edge of node |\n| `bottom` | Bottom edge of node |\n| `left` | Left edge of node |\n\n### End Shapes\n\n| Value | Description |\n|-------|-------------|\n| `none` | No endpoint shape |\n| `arrow` | Arrow endpoint |\n\n## Colors\n\nThe `canvasColor` type can be specified in two ways:\n\n### Hex Colors\n\n```json\n{\n  \"color\": \"#FF0000\"\n}\n```\n\n### Preset Colors\n\n```json\n{\n  \"color\": \"1\"\n}\n```\n\n| Preset | Color |\n|--------|-------|\n| `\"1\"` | Red |\n| `\"2\"` | Orange |\n| `\"3\"` | Yellow |\n| `\"4\"` | Green |\n| `\"5\"` | Cyan |\n| `\"6\"` | Purple |\n\nNote: Specific color values for presets are intentionally undefined, allowing applications to use their own brand colors.\n\n## Complete Examples\n\n### Simple Canvas with Text and Connections\n\n```json\n{\n  \"nodes\": [\n    {\n      \"id\": \"8a9b0c1d2e3f4a5b\",\n      \"type\": \"text\",\n      \"x\": 0,\n      \"y\": 0,\n      \"width\": 300,\n      \"height\": 150,\n      \"text\": \"# Main Idea\\n\\nThis is the central concept.\"\n    },\n    {\n      \"id\": \"1a2b3c4d5e6f7a8b\",\n      \"type\": \"text\",\n      \"x\": 400,\n      \"y\": -100,\n      \"width\": 250,\n      \"height\": 100,\n      \"text\": \"## Supporting Point A\\n\\nDetails here.\"\n    },\n    {\n      \"id\": \"2b3c4d5e6f7a8b9c\",\n      \"type\": \"text\",\n      \"x\": 400,\n      \"y\": 100,\n      \"width\": 250,\n      \"height\": 100,\n      \"text\": \"## Supporting Point B\\n\\nMore details.\"\n    }\n  ],\n  \"edges\": [\n    {\n      \"id\": \"3c4d5e6f7a8b9c0d\",\n      \"fromNode\": \"8a9b0c1d2e3f4a5b\",\n      \"fromSide\": \"right\",\n      \"toNode\": \"1a2b3c4d5e6f7a8b\",\n      \"toSide\": \"left\"\n    },\n    {\n      \"id\": \"4d5e6f7a8b9c0d1e\",\n      \"fromNode\": \"8a9b0c1d2e3f4a5b\",\n      \"fromSide\": \"right\",\n      \"toNode\": \"2b3c4d5e6f7a8b9c\",\n      \"toSide\": \"left\"\n    }\n  ]\n}\n```\n\n### Project Board with Groups\n\n```json\n{\n  \"nodes\": [\n    {\n      \"id\": \"5e6f7a8b9c0d1e2f\",\n      \"type\": \"group\",\n      \"x\": 0,\n      \"y\": 0,\n      \"width\": 300,\n      \"height\": 500,\n      \"label\": \"To Do\",\n      \"color\": \"1\"\n    },\n    {\n      \"id\": \"6f7a8b9c0d1e2f3a\",\n      \"type\": \"group\",\n      \"x\": 350,\n      \"y\": 0,\n      \"width\": 300,\n      \"height\": 500,\n      \"label\": \"In Progress\",\n      \"color\": \"3\"\n    },\n    {\n      \"id\": \"7a8b9c0d1e2f3a4b\",\n      \"type\": \"group\",\n      \"x\": 700,\n      \"y\": 0,\n      \"width\": 300,\n      \"height\": 500,\n      \"label\": \"Done\",\n      \"color\": \"4\"\n    },\n    {\n      \"id\": \"8b9c0d1e2f3a4b5c\",\n      \"type\": \"text\",\n      \"x\": 20,\n      \"y\": 50,\n      \"width\": 260,\n      \"height\": 80,\n      \"text\": \"## Task 1\\n\\nImplement feature X\"\n    },\n    {\n      \"id\": \"9c0d1e2f3a4b5c6d\",\n      \"type\": \"text\",\n      \"x\": 370,\n      \"y\": 50,\n      \"width\": 260,\n      \"height\": 80,\n      \"text\": \"## Task 2\\n\\nReview PR #123\",\n      \"color\": \"2\"\n    },\n    {\n      \"id\": \"0d1e2f3a4b5c6d7e\",\n      \"type\": \"text\",\n      \"x\": 720,\n      \"y\": 50,\n      \"width\": 260,\n      \"height\": 80,\n      \"text\": \"## Task 3\\n\\n~~Setup CI/CD~~\"\n    }\n  ],\n  \"edges\": []\n}\n```\n\n### Research Canvas with Files and Links\n\n```json\n{\n  \"nodes\": [\n    {\n      \"id\": \"1e2f3a4b5c6d7e8f\",\n      \"type\": \"text\",\n      \"x\": 300,\n      \"y\": 200,\n      \"width\": 400,\n      \"height\": 200,\n      \"text\": \"# Research Topic\\n\\n## Key Questions\\n\\n- How does X affect Y?\\n- What are the implications?\",\n      \"color\": \"5\"\n    },\n    {\n      \"id\": \"2f3a4b5c6d7e8f9a\",\n      \"type\": \"file\",\n      \"x\": 0,\n      \"y\": 0,\n      \"width\": 250,\n      \"height\": 150,\n      \"file\": \"Literature/Paper A.pdf\"\n    },\n    {\n      \"id\": \"3a4b5c6d7e8f9a0b\",\n      \"type\": \"file\",\n      \"x\": 0,\n      \"y\": 200,\n      \"width\": 250,\n      \"height\": 150,\n      \"file\": \"Notes/Meeting Notes.md\",\n      \"subpath\": \"#Key Insights\"\n    },\n    {\n      \"id\": \"4b5c6d7e8f9a0b1c\",\n      \"type\": \"link\",\n      \"x\": 0,\n      \"y\": 400,\n      \"width\": 250,\n      \"height\": 100,\n      \"url\": \"https://example.com/research\"\n    },\n    {\n      \"id\": \"5c6d7e8f9a0b1c2d\",\n      \"type\": \"file\",\n      \"x\": 750,\n      \"y\": 150,\n      \"width\": 300,\n      \"height\": 250,\n      \"file\": \"Attachments/diagram.png\"\n    }\n  ],\n  \"edges\": [\n    {\n      \"id\": \"6d7e8f9a0b1c2d3e\",\n      \"fromNode\": \"2f3a4b5c6d7e8f9a\",\n      \"fromSide\": \"right\",\n      \"toNode\": \"1e2f3a4b5c6d7e8f\",\n      \"toSide\": \"left\",\n      \"label\": \"supports\"\n    },\n    {\n      \"id\": \"7e8f9a0b1c2d3e4f\",\n      \"fromNode\": \"3a4b5c6d7e8f9a0b\",\n      \"fromSide\": \"right\",\n      \"toNode\": \"1e2f3a4b5c6d7e8f\",\n      \"toSide\": \"left\",\n      \"label\": \"informs\"\n    },\n    {\n      \"id\": \"8f9a0b1c2d3e4f5a\",\n      \"fromNode\": \"4b5c6d7e8f9a0b1c\",\n      \"fromSide\": \"right\",\n      \"toNode\": \"1e2f3a4b5c6d7e8f\",\n      \"toSide\": \"left\",\n      \"toEnd\": \"arrow\",\n      \"color\": \"6\"\n    },\n    {\n      \"id\": \"9a0b1c2d3e4f5a6b\",\n      \"fromNode\": \"1e2f3a4b5c6d7e8f\",\n      \"fromSide\": \"right\",\n      \"toNode\": \"5c6d7e8f9a0b1c2d\",\n      \"toSide\": \"left\",\n      \"label\": \"visualized by\"\n    }\n  ]\n}\n```\n\n### Flowchart\n\n```json\n{\n  \"nodes\": [\n    {\n      \"id\": \"a0b1c2d3e4f5a6b7\",\n      \"type\": \"text\",\n      \"x\": 200,\n      \"y\": 0,\n      \"width\": 150,\n      \"height\": 60,\n      \"text\": \"**Start**\",\n      \"color\": \"4\"\n    },\n    {\n      \"id\": \"b1c2d3e4f5a6b7c8\",\n      \"type\": \"text\",\n      \"x\": 200,\n      \"y\": 100,\n      \"width\": 150,\n      \"height\": 60,\n      \"text\": \"Step 1:\\nGather data\"\n    },\n    {\n      \"id\": \"c2d3e4f5a6b7c8d9\",\n      \"type\": \"text\",\n      \"x\": 200,\n      \"y\": 200,\n      \"width\": 150,\n      \"height\": 80,\n      \"text\": \"**Decision**\\n\\nIs data valid?\",\n      \"color\": \"3\"\n    },\n    {\n      \"id\": \"d3e4f5a6b7c8d9e0\",\n      \"type\": \"text\",\n      \"x\": 400,\n      \"y\": 200,\n      \"width\": 150,\n      \"height\": 60,\n      \"text\": \"Process data\"\n    },\n    {\n      \"id\": \"e4f5a6b7c8d9e0f1\",\n      \"type\": \"text\",\n      \"x\": 0,\n      \"y\": 200,\n      \"width\": 150,\n      \"height\": 60,\n      \"text\": \"Request new data\",\n      \"color\": \"1\"\n    },\n    {\n      \"id\": \"f5a6b7c8d9e0f1a2\",\n      \"type\": \"text\",\n      \"x\": 400,\n      \"y\": 320,\n      \"width\": 150,\n      \"height\": 60,\n      \"text\": \"**End**\",\n      \"color\": \"4\"\n    }\n  ],\n  \"edges\": [\n    {\n      \"id\": \"a6b7c8d9e0f1a2b3\",\n      \"fromNode\": \"a0b1c2d3e4f5a6b7\",\n      \"fromSide\": \"bottom\",\n      \"toNode\": \"b1c2d3e4f5a6b7c8\",\n      \"toSide\": \"top\"\n    },\n    {\n      \"id\": \"b7c8d9e0f1a2b3c4\",\n      \"fromNode\": \"b1c2d3e4f5a6b7c8\",\n      \"fromSide\": \"bottom\",\n      \"toNode\": \"c2d3e4f5a6b7c8d9\",\n      \"toSide\": \"top\"\n    },\n    {\n      \"id\": \"c8d9e0f1a2b3c4d5\",\n      \"fromNode\": \"c2d3e4f5a6b7c8d9\",\n      \"fromSide\": \"right\",\n      \"toNode\": \"d3e4f5a6b7c8d9e0\",\n      \"toSide\": \"left\",\n      \"label\": \"Yes\",\n      \"color\": \"4\"\n    },\n    {\n      \"id\": \"d9e0f1a2b3c4d5e6\",\n      \"fromNode\": \"c2d3e4f5a6b7c8d9\",\n      \"fromSide\": \"left\",\n      \"toNode\": \"e4f5a6b7c8d9e0f1\",\n      \"toSide\": \"right\",\n      \"label\": \"No\",\n      \"color\": \"1\"\n    },\n    {\n      \"id\": \"e0f1a2b3c4d5e6f7\",\n      \"fromNode\": \"e4f5a6b7c8d9e0f1\",\n      \"fromSide\": \"top\",\n      \"fromEnd\": \"none\",\n      \"toNode\": \"b1c2d3e4f5a6b7c8\",\n      \"toSide\": \"left\",\n      \"toEnd\": \"arrow\"\n    },\n    {\n      \"id\": \"f1a2b3c4d5e6f7a8\",\n      \"fromNode\": \"d3e4f5a6b7c8d9e0\",\n      \"fromSide\": \"bottom\",\n      \"toNode\": \"f5a6b7c8d9e0f1a2\",\n      \"toSide\": \"top\"\n    }\n  ]\n}\n```\n\n## ID Generation\n\nNode and edge IDs must be unique strings. Obsidian generates 16-character hexadecimal IDs:\n\n```json\n\"id\": \"6f0ad84f44ce9c17\"\n\"id\": \"a3b2c1d0e9f8g7h6\"\n\"id\": \"1234567890abcdef\"\n```\n\nThis format is a 16-character lowercase hex string (64-bit random value).\n\n## Layout Guidelines\n\n### Positioning\n\n- Coordinates can be negative (canvas extends infinitely)\n- `x` increases to the right\n- `y` increases downward\n- Position refers to top-left corner of node\n\n### Recommended Sizes\n\n| Node Type | Suggested Width | Suggested Height |\n|-----------|-----------------|------------------|\n| Small text | 200-300 | 80-150 |\n| Medium text | 300-450 | 150-300 |\n| Large text | 400-600 | 300-500 |\n| File preview | 300-500 | 200-400 |\n| Link preview | 250-400 | 100-200 |\n| Group | Varies | Varies |\n\n### Spacing\n\n- Leave 20-50px padding inside groups\n- Space nodes 50-100px apart for readability\n- Align nodes to grid (multiples of 10 or 20) for cleaner layouts\n\n## Validation Rules\n\n1. All `id` values must be unique across nodes and edges\n2. `fromNode` and `toNode` must reference existing node IDs\n3. Required fields must be present for each node type\n4. `type` must be one of: `text`, `file`, `link`, `group`\n5. `backgroundStyle` must be one of: `cover`, `ratio`, `repeat`\n6. `fromSide`, `toSide` must be one of: `top`, `right`, `bottom`, `left`\n7. `fromEnd`, `toEnd` must be one of: `none`, `arrow`\n8. Color presets must be `\"1\"` through `\"6\"` or valid hex color\n\n## References\n\n- [JSON Canvas Spec 1.0](https://jsoncanvas.org/spec/1.0/)\n- [JSON Canvas GitHub](https://github.com/obsidianmd/jsoncanvas)","author":"@anbeime","ownerProfile":null,"authorContacts":null,"sourceUrl":"https://github.com/anbeime/skill/tree/main/skills/obsidian-skills-integrated/json-canvas","license":"MIT","category":null,"lang":"en","tokens":5068,"stars":0,"calls30d":1,"claimed":false,"visibility":"public","origin":"crawler","version":"0.1.0","createdAt":"2026-08-22","updatedAt":"2026-08-22","files":[],"requires":{"mcp":[],"tools":[]},"safety":{"flags":[],"scannedAt":"2026-08-22","hasScripts":false,"networkEndpoints":["jsoncanvas.org","obsidian.md"]}}