Board is a self-hosted tldraw instance built for one thing: a canvas that a person on an iPad and an AI agent can both draw on, at the same time, on the same board. Open a board URL on any device and everyone sees the same live room. Every board is scoped to a Clerk Organization workspace, so a client's canvas stays a client's canvas.
The image links to the committed self-contained map. After cloning or downloading the repository, open docs/architecture/architecture.html locally to search components, trace relationships, switch themes, and export the diagram.
- Shared board URLs. Any board ID in the URL becomes its own room —
board/client-a,board/wireframes, whatever the workspace needs. Open the same URL on iPad and Mac to see the same live canvas. - Workspace-scoped by Clerk. Sign-in and Organizations are the boundary. Select or create an Organization before opening a board; boards belong to the active Organization.
- Durable storage. InsForge/Postgres is the sole durable store — workspaces, memberships, boards, snapshots, and integration tokens. Live rooms hold state in memory only while active; Board restores and persists the Postgres snapshot around that.
- REST API for agents and apps. Read or write the same tldraw records the web editor uses — list boards, fetch a snapshot, create/update/delete shapes — authenticated with a Clerk organization JWT or a scoped
bd_Board workspace token. - MCP for coding agents.
list_boards,read_board,get_board_snapshot,create_shapes,update_shapes,delete_shapesover Streamable HTTP, so an agent can inspect and draw on board state directly.
cp .env.example .env # set Clerk keys + DATABASE_URL
docker compose up -d --buildOpen a board:
http://<server-ip>:5421/board/personal-sketchbook
Use the hamburger menu for New board, View boards, and the Organization switcher. The top action row's copy-link icon copies the current board URL and opens the Clerk Organization members view, so inviting a teammate to a board is one click.
Run a single Board server instance — horizontal scaling needs shared room coordination and isn't supported yet.
Uploaded assets live under /home/vps-apps/tldraw-selfhost/data/uploads. The Docker volume stores uploaded media only; board documents live in Postgres, not the volume.
To erase all Board-owned boards, snapshots, integration tokens, and local media while preserving workspace and membership rows:
BOARD_RESET_CONFIRM=DELETE_BOARD_DATA npm run reset:board-dataGET /api/health
GET /api/boards
GET /api/boards/:roomId
GET /api/boards/:roomId/snapshot
POST /api/boards/:roomId/records
DELETE /api/boards/:roomId/records
Authenticate with Authorization: Bearer <Clerk organization JWT> or a bd_... workspace token (create one from the Board hamburger menu via Copy Connections token, or via POST /api/integration-tokens). The OpenAPI document is served at /openapi.json. Write endpoints accept raw tldraw records — the same id, typeName, type, x, y, props shape the editor stores internally.
http://<server-ip>:5421/mcp
Connect with Streamable HTTP. Tools: list_boards, read_board, get_board_snapshot, create_shapes, update_shapes, delete_shapes — all operating on raw tldraw records.
On this VPS, Board is published on port 5421. From devices on the same Tailnet, use the Tailscale IP or MagicDNS name:
http://100.123.30.5:5421/board/personal-sketchbook
Keep it behind Tailscale or add authentication before exposing it publicly.
tldraw SDK production use requires a license key:
VITE_TLDRAW_LICENSE_KEY="tldraw-..." docker compose up -d --buildBuilt by Fractals
