From expansion
Generate Obsidian Canvas (.canvas) files for UX flows, data flows, and testing infrastructure visualization
How this skill is triggered — by the user, by Claude, or both
Slash command
/expansion:canvas-diagramsWhen to use
when user asks to visualize architecture, flows, data pipelines, testing infrastructure, or says "canvas", "diagram", "flow chart", "visualize"
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Generate Obsidian `.canvas` files that visually represent system architecture, user flows, data pipelines, and testing infrastructure. These are collaborative artifacts — Claude generates them, the user can manually adjust layout in Obsidian, and Claude can read them back to understand current architecture.
Generate Obsidian .canvas files that visually represent system architecture, user flows, data pipelines, and testing infrastructure. These are collaborative artifacts — Claude generates them, the user can manually adjust layout in Obsidian, and Claude can read them back to understand current architecture.
Announce at start: "Using Canvas Diagrams skill to generate a visual [type] canvas."
Vault base: /Users/aditya/Library/CloudStorage/[email protected]/My Drive/Exocortex/
Projects root: Research/Projects/
Project folder resolution (MANDATORY before writing any canvas):
MapTPOT, "Temporal Coordination" → TemporalCoordination)Research/Projects/<ProjectFolder>/ exists in the vaultmkdir -p "<vault_base>/Research/Projects/<ProjectFolder>/"docs/diagrams/ directory (version-controlled)Two copies: Canvases live in both the Exocortex vault (for Obsidian viewing) and the project repo (for git tracking). The vault copy is the primary viewing artifact; the repo copy ensures canvases survive if the vault is unavailable.
Naming convention: <type>-<scope>[-detail].canvas
Examples at each resolution:
data-flow-overview.canvas (system level)data-flow-export-pipeline.canvas (subsystem level)data-flow-context-assembly.canvas (function level)Generation order: BOTTOM-UP. Create detailed subsystem canvases first, then aggregate into an overview that embeds them.
![[filename.canvas]] in the node textUse type: "file" nodes to embed sub-canvases — NOT ![[...]] syntax in text nodes (that's for markdown notes only).
{"id": "embed_subsystem", "type": "file", "file": "vault/relative/path/to/sub-canvas.canvas", "x": 0, "y": 100, "width": 400, "height": 300}
Pattern for overview canvases:
Vault-relative paths (from Exocortex vault root):
Research/Projects/<ProjectFolder>/<filename>.canvasux-flow-*.canvas)Maps user journeys through the system.
Node categories & colors:
| Element | Color | Meaning |
|---|---|---|
| User action | "4" (green) | Something the user does |
| System response | "5" (cyan) | What the system shows/does |
| Decision point | "2" (orange) | Branch in the flow |
| Error/edge case | "1" (red) | Failure states |
| External trigger | "6" (purple) | Incoming webhook, notification |
data-flow-*.canvas)Maps data sources, transformations, API calls, and storage.
Node categories & colors:
| Element | Color | Meaning |
|---|---|---|
| Data source | "4" (green) | External APIs, webhooks, user input |
| Transform/function | "5" (cyan) | Processing logic |
| Storage | "6" (purple) | Database, file system |
| API endpoint | "2" (orange) | Exposed routes |
| LLM call | "3" (yellow) | AI processing step |
| Error/retry | "1" (red) | Failure handling |
testing-infra-*.canvas)Maps what's tested, how, and where gaps exist.
Node categories & colors:
| Element | Color | Meaning |
|---|---|---|
| Tested (passing) | "4" (green) | Has tests, they pass |
| Tested (failing) | "1" (red) | Has tests, they fail |
| Untested | "2" (orange) | No test coverage |
| Test file | "5" (cyan) | The test file itself |
| Mock/fixture | "6" (purple) | Test infrastructure |
| CI/runner | "3" (yellow) | How tests are executed |
data-flow-*-fields.canvas)Maps API response fields to storage decisions. Shows what data is available, what's retained, and what's discarded.
Node categories & colors:
| Element | Color | Meaning |
|---|---|---|
| API field (source) | "4" (green) | Raw data available from external API |
| Processing step | "5" (cyan) | Transformation before storage |
| Storage destination | "6" (purple) | Where data lands (table.column) |
| Ephemeral use | "3" (yellow) | Used for matching/scoring, never persisted |
| Discarded | "1" (red) | Explicitly not stored |
Edge colors for data fate:
| Edge meaning | Color |
|---|---|
| Retained (stored) | "4" (green) |
| Processing flow | "5" (cyan) |
| Discarded (not stored) | "1" (red) |
Use a red ("1") group labeled "Discarded" to explicitly show fields/data that are available but intentionally not persisted. This makes data decisions visible and reviewable — a viewer can question "should we actually be storing X?"
Important Obsidian behaviors:
fromEnd/toEnd default to no arrow; only specify when you want arrows{
"nodes": [
{"id": "group_id", "type": "group", "x": -50, "y": -50, "width": 700, "height": 400, "color": "5", "label": "Group Label"},
{"id": "unique_snake_case_id", "type": "text", "text": "# Node Title\n\nDescription.\n\n`file_path:line`", "x": 0, "y": 0, "width": 300, "height": 150, "color": "4"}
],
"edges": [
{"id": "edge_unique_id", "fromNode": "source_node_id", "fromSide": "bottom", "toNode": "target_node_id", "toSide": "top", "color": "3", "label": "verb"}
]
}
Node field order (matches Obsidian's output): id, type, text|label, x, y, width, height, color
Edge field order: id, fromNode, fromSide, toNode, toSide, color, label
Breathe. Nodes need white space to be skimmable. Err on the side of too spread out — the user can zoom in Obsidian but can't un-overlap nodes easily.
For data-mapping canvases (L3b), use left-to-right flow instead of vertical:
Column spacing: 500-550px between groups. Each group contains its nodes stacked vertically.
Title must never wrap. The # heading line determines minimum width. Body text can be clipped (user scrolls in Obsidian), but the title must be fully visible on one line.
Width calculation (title-driven):
# levelwidth = max(200, len(title_text) * 14 + 40)# beeper_ingestion_agent (24 chars) → min 376px wide# Cache Check (13 chars) → min 222px wideHeight calculation (body-driven):
height = 50 + (num_body_lines * 28)Practical sizes:
| Content | Width | Height |
|---|---|---|
| Title only | 250-350w | 60h |
| Title + 1-2 lines | 280-380w | 100-120h |
| Title + 3-5 lines + code ref | 320-420w | 160-200h |
| Title + bullet list (6-8 items) | 350-420w | 220-280h |
Colors should be scannable at a glance. A viewer should understand the system's structure from colors alone, before reading any text.
Principles:
Edge coloring:
| Edge meaning | Color |
|---|---|
| Primary data flow | "4" (green) |
| LLM/AI processing | "3" (yellow) |
| Storage write | "6" (purple) |
| API/HTTP call | "2" (orange) |
| Error/retry path | "1" (red) |
| Control flow (triggers) | "5" (cyan) |
Group coloring:
#1 rule: Drop obvious labels. If node names imply the relationship, use color-only edges.
Strategies:
toSide values (left, top, right) so edges arrive at different points.fromSide values to radiate edges instead of bundling.fromSide: "right" → toSide: "left" to go around the right edge).After generating a canvas, run the PNG preview script to check for:
# Quick overlap/preview check (run from project root)
.venv/bin/python3 scripts/canvas_preview.py <canvas_file>
Use logical connection points:
fromSide: "bottom", toSide: "top"fromSide: "right", toSide: "left"fromEnd: "arrow", toEnd: "arrow"# Short Title
Brief description (1-2 sentences).
`path/to/relevant/file.py:42`
# Decision: [Question]
**Yes →** [outcome]
**No →** [outcome]
# function_name()
**In:** param types
**Out:** return type
**Side effects:** what it changes
`path/to/file.py:123`
.canvas file![[subsystem-canvas.canvas]] in each node
c. Minimal edges showing major flows between subsystems.canvas file (respect user's manual layout adjustments)When asked to update or discuss an existing canvas:
.canvas file from the target directory> [!note] callouts in node text for Claude-to-human notesUse short, active verbs:
triggers, calls, returns, stores, reads, transformson success, on error, if true, if falsevia webhook, via API, via cronfile:line formatGuides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.
npx claudepluginhub anantham/expansion --plugin expansion