Skip to content
← Tools

tldraw

Thinking and explaining on a canvas

An infinite drawing canvas for boxes, arrows and notes. Its files are plain JSON, so a diagram can be generated by a script and then dragged around by hand.

Most of what I build is a graph: a table feeding three tables, each feeding a campaign, with gates in between. Those are much easier to argue about as a picture than as a list of column names. tldraw is where that picture goes when it needs to be moved around, annotated, or shown to someone.

How I use it

Generated first, arranged by hand. I build the file from a small spec of nodes and edges, so the boxes and arrows are correct before I touch them, and then I drag things until the layout says what I mean. Generating gets the facts right. Hand arranging gets the emphasis right, and no automatic layout has ever picked the emphasis I wanted.

One diagram per question. A fifty node picture of an entire system is a wall, not an explanation. I draw the company level flow, then the person level flow, then the push path, as separate pictures. Each one answers one question and fits on a screen.

The same spec drives both formats. Node and edge definitions live in one file and can be rendered either as a text diagram for the repository or as a canvas. Which means switching between them is a choice about the audience, not a rebuild.

Text diagrams for the repo, canvas for the conversation. A text based diagram diffs in version control and rebuilds itself from live data. tldraw is the one I open when I am still deciding what the thing should be, or when I am walking someone through it and expect to be interrupted.

What I have learned the hard way

Text lives in a rich text field, not a plain one. The obvious plain text property still exists and is deprecated, so a file written with it loads as a diagram full of empty boxes. This was the single biggest cause of blank output when I started generating files, and it fails quietly rather than refusing to open.

The file validator rejects any key it does not recognise. Leave one debugging field on a shape while you are working and the whole file is invalid, not just that shape. Useful strictness, harsh the first time.

A file that parses is not a file that opens. The only check I trust is rendering the diagram to an image and looking at it. Valid JSON with the wrong shape records produces a perfectly well formed picture of nothing.

The palette is fixed, so brand colours do not survive. A colour that is not in the set is silently mapped to the nearest one it has, which is fine for thinking and wrong for anything that is supposed to match a design.

Resources

This is one part of a stack. The rest is on the tools page, and what I build with it is on work.

tools/tldraw.md
---
tool: tldraw
role: Thinking and explaining on a canvas
category: Building
url: https://mihajlomaiga.com/tools/tldraw
---

# tldraw
An infinite drawing canvas for boxes, arrows and notes. Its files are plain JSON, so a diagram can be generated by a script and then dragged around by hand.
Most of what I build is a graph: a table feeding three tables, each feeding a
campaign, with gates in between. Those are much easier to argue about as a picture
than as a list of column names. tldraw is where that picture goes when it needs to
be moved around, annotated, or shown to someone.

## How I use it

**Generated first, arranged by hand.** I build the file from a small spec of nodes
and edges, so the boxes and arrows are correct before I touch them, and then I drag
things until the layout says what I mean. Generating gets the facts right. Hand
arranging gets the emphasis right, and no automatic layout has ever picked the
emphasis I wanted.

**One diagram per question.** A fifty node picture of an entire system is a wall,
not an explanation. I draw the company level flow, then the person level flow, then
the push path, as separate pictures. Each one answers one question and fits on a
screen.

**The same spec drives both formats.** Node and edge definitions live in one file
and can be rendered either as a text diagram for the repository or as a canvas.
Which means switching between them is a choice about the audience, not a rebuild.

**Text diagrams for the repo, canvas for the conversation.** A text based diagram
diffs in version control and rebuilds itself from live data. tldraw is the one I
open when I am still deciding what the thing should be, or when I am walking
someone through it and expect to be interrupted.

## What I have learned the hard way

**Text lives in a rich text field, not a plain one.** The obvious plain text
property still exists and is deprecated, so a file written with it loads as a
diagram full of empty boxes. This was the single biggest cause of blank output when
I started generating files, and it fails quietly rather than refusing to open.

**The file validator rejects any key it does not recognise.** Leave one debugging
field on a shape while you are working and the whole file is invalid, not just that
shape. Useful strictness, harsh the first time.

**A file that parses is not a file that opens.** The only check I trust is
rendering the diagram to an image and looking at it. Valid JSON with the wrong
shape records produces a perfectly well formed picture of nothing.

**The palette is fixed, so brand colours do not survive.** A colour that is not in
the set is silently mapped to the nearest one it has, which is fine for thinking
and wrong for anything that is supposed to match a design.
## Resources
- [tldraw](https://www.tldraw.com/)
- [Developer docs](https://tldraw.dev/)