# Editable canvases

> Build a whiteboard your team can keep editing, with arrows that stay attached, cards that hold their own words, and an agent that follows comments.

Module: Diagrams · Level: intermediate · 6 min · https://school.agents.org.in/visual/diagrams/editable-canvases

Two canvases, one move. Someone dragged the blue card down on both. Drag it again, or press Move the card, and watch the two arrows.

*[Interactive demo: A bound arrow is a real connection, so it follows. An arrow drawn to look attached is left pointing at nothing.]*

Before the move, both arrows looked identical. Only one survived the drag. That is the whole lesson in one move: **a canvas is worth what survives the next person's drag**.

A finished figure is drawn once for readers. A canvas (An endless editable whiteboard, like tldraw or FigJam, where a team keeps moving boxes and arrows around after the first draft) is for pictures people keep editing. So build it from real relationships (arrows bound to shapes, cards grouped in frames), not from coordinates that only happen to look right today.

## Which tldraw to use

tldraw is an open-ended whiteboard, and it gives agents three ways in. Which one you use depends on where you are.

  **tldraw Desktop:**

You have the app open with a `.tldraw` file. The app's agent setup installs a `tldraw-offline` skill and helper. It talks to a small local server: one call to search the board, one to run edits. Hand long jobs to its helper.

  **Hosted chat:**

No app installed: you are in Claude, ChatGPT or Cursor. Use the tldraw MCP app, one address you add as a connector. Its `search` tool reads how the editor works; `exec` runs code against the live board.

  **Your own product:**

You are building a canvas into your app. That is the tldraw SDK, with a `tldraw-migrate` skill for upgrades. The skill only covers the UI craft here.

> **They speak different formats.** Desktop takes raw tldraw records. The MCP app takes simpler shapes with string ids. Never paste a snippet from one into the other; read the surface's own search first.

## Six rules for a board that stays editable

  **Step: Bind every meaningful arrow.** Create arrows with `helpers.createArrowBetweenShapes`, so they are bound (An arrow on a canvas that is truly attached to the shapes at its ends, so it follows them when someone drags. An arrow that only looks attached gets left behind) to both shapes. A raw arrow placed by coordinates detaches on the next drag. Unbound arrows are for decoration only.

  **Step: Generate structure, don't place it.** A flowchart, sequence, state machine or mind map comes from `helpers.mermaid(source)`, which writes bound shapes for you. On a canvas, Mermaid (A way to write a diagram as short text (A --> B) that a docs site turns into a picture. Good for structure kept next to code; its automatic layout looks generated in a finished figure) is the right start, because people rearrange the result.

  **Step: A card and its words are one shape.** Put the label inside the shape's own text. A long label needs a bigger card, not a separate text box laid on top. Loose text is only for words that stand alone, like a heading over a group.

  **Step: Arrange with the editor, not arithmetic.** Use align, stack and distribute, and draw containers as frames. Shapes inside a frame are positioned relative to it, and text never crosses a frame's edge.

  **Step: Lint before you call it done.** Run `helpers.getLints()` and fix every lint (An automatic check that flags problems on a board, like text spilling out of a card or an arrow that isn't attached. Fix every one your edit caused) your edit introduced, on the shapes you touched. Don't tidy a neighbour nobody asked you to move.

  **Step: One accent here too.** Canvas colors are names (`blue`, `orange`, `grey`), not hex codes. Pick one named color for the focal shapes and keep the rest neutral.

  **Before (avoid):**

Twelve boxes placed by x and y, each with a text shape floating over it, arrows drawn from point to point. Looks perfect. Someone drags one box and three arrows and two labels stay behind.

  **After (do this):**

The same flow generated from a Mermaid source: labels inside their cards, arrows bound, the whole thing in a frame. Drag anything and it all comes along.

## People share the board

A canvas is a team's space, and an agent working on it is a guest. Three habits make it a good one.

**Comments are instructions with an address.** An anchored comment (A comment pinned to a specific shape, so it points at what it means instead of describing it. On a board, each one is an instruction with an address) is pinned to the shapes it means, so the agent reads the threads first and uses each anchor to find its target. It replies in the thread it acted on and resolves it. A thread addressed to someone else is not its job.

**Ambiguity stops the edit.** "Make the important one stand out" over six identical cards is a question. An unanswered question is not permission to pick one.

*(Pointing beats describing, on a canvas too.)*

**Scripts are code.** A board can carry scripts that run whenever the file opens. So treat a `.tldraw` file from someone else the way you'd treat code from someone else, and ask before writing to a board whose scripts you didn't start.

Two more small things on Desktop: never edit a `.tldraw` file while it's open in the app, and save with `helpers.saveDoc()` yourself instead of asking the person to.

## When the board becomes a figure

Boards often grow into something worth publishing. When that happens, redraw it as a finished figure from the board's **structure**: its shapes and the bindings between them. Don't screenshot it. A screenshot keeps the mess and loses the meaning.

**Work on a shared board (paste into your agent):**

```text
Open the planning board in tldraw.
First read every comment thread; act only on threads addressed to you, reply in that thread, then resolve it.
Build the signup flow from a Mermaid source so every arrow is bound. Labels go inside their cards; group the flow in a frame.
Use one named color (blue) for the focal step and grey for the rest.
Run getLints and fix every lint your edit introduced. Don't move shapes you weren't asked to touch.
If a request is ambiguous (which card is "the important one"?), ask me instead of guessing.
```

**Check yourself:** An agent draws a flowchart on a tldraw board by placing boxes and arrows at exact coordinates. It looks perfect. What will go wrong first?

- [ ] The colors won't match the brand's hex codes
- [x] The arrows detach as soon as someone drags a box
- [ ] The board will be too slow to open
- [ ] Mermaid will refuse to import it

*Why:* Arrows placed by coordinates only look attached. Bound arrows, created with createArrowBetweenShapes or generated from Mermaid, follow the shapes when people rearrange them.

## In the skill

- https://school.agents.org.in/skill/diagram/tldraw-canvas.md
