This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This is the tldraw monorepo - an infinite canvas SDK for React applications. It's organized using yarn workspaces with packages for the core editor, UI components, shapes, tools, and supporting infrastructure.
Important: There are CONTEXT.md files throughout this repository designed specifically for AI agents. Always read the relevant CONTEXT.md files to understand packages and their architecture.
yarn dev- Start development server for examples app (main SDK showcase)yarn dev-app- Start tldraw.com client app developmentyarn dev-docs- Start documentation site developmentyarn dev-vscode- Start VSCode extension developmentyarn dev-template <template name>- Runs a templateyarn context- Find and display nearest CONTEXT.md file (supports -v, -r, -u flags)yarn refresh-context- Update CONTEXT.md files using Claude Code CLI
yarn test runin root - Run all tests (slow, avoid unless necessary)yarn test runin a workspace - Run tests in specific workspace (cd to workspace first)yarn e2e- Run end-to-end tests for examplesyarn e2e-dotcom- Run end-to-end tests for tldraw.com
yarn lint- Lint packageyarn typecheckin workspace root - Type check all packagesyarn format- Format code with Prettieryarn api-check- Validate public API consistency
IMPORTANT: NEVER run bare tsc - always use yarn typecheck.
If the typecheck command is not found, it's because you're not running it from the root of the repo.
@tldraw/editor - Foundational infinite canvas editor
- No shapes, tools, or UI - just the core engine
- State management using reactive signals (@tldraw/state)
- Shape system via ShapeUtil, Tools via StateNode
- Bindings system for shape relationships
@tldraw/tldraw - Complete "batteries included" SDK
- Builds on editor with full UI, shapes, and tools
- Default shape utilities (text, draw, geo, arrow, etc.)
- Complete tool set (select, hand, eraser, etc.)
- Responsive UI system with customizable components
@tldraw/store - Reactive client-side database
- Document persistence with IndexedDB
- Reactive updates using signals
- Migration system for schema changes
@tldraw/tlschema - Type definitions and validators
- Shape, binding, and record type definitions
- Validation schemas and migrations
- Shared data structures
Reactive state management
- Uses @tldraw/state for reactive signals (Atom, Computed)
- All editor state is reactive and observable
- Automatic dependency tracking prevents unnecessary re-renders
Shape system
- Each shape type has a ShapeUtil class defining behavior
- ShapeUtil handles geometry, rendering, interactions
- Extensible - custom shapes via new ShapeUtil implementations
Tools as state machines
- Tools implemented as StateNode hierarchies
- Event-driven with pointer, keyboard, tick handlers
- Complex tools have child states (e.g., SelectTool has Brushing, Translating, etc.)
Bindings system
- Relationships between shapes (arrows to shapes, etc.)
- BindingUtil classes define binding behavior
- Automatic updates when connected shapes change
Vitest tests
- Unit tests: name test files after the file being tested (e.g.,
LicenseManager.test.ts) - Integration tests: use
src/test/feature-name.test.tsformat - Test in tldraw workspace if you need default shapes/tools
Running tests
- Run from specific workspace directory:
cd packages/editor && yarn test run - Filter with additional args:
yarn test run --grep "selection" - Avoid
yarn testfrom root (slow and hard to filter)
Playwright E2E tests
- Located in
apps/examples/e2e/andapps/dotcom/client/e2e/ - Use
yarn e2eandyarn e2e-dotcomcommands
apps/
├── examples/ # SDK examples and demos
├── docs/ # Documentation site (tldraw.dev)
├── dotcom/ # tldraw.com application
│ ├── client/ # Frontend React app
│ ├── sync-worker/ # Multiplayer backend
│ └── asset-upload-worker/
└── vscode/ # VSCode extension
packages/
├── editor/ # Core editor engine
├── tldraw/ # Complete SDK with UI
├── store/ # Reactive database
├── tlschema/ # Type definitions
├── state/ # Reactive signals library
├── sync/ # Multiplayer SDK
├── utils/ # Shared utilities
├── validate/ # Lightweight validation library
├── assets/ # Icons, fonts, translations
└── create-tldraw/ # npm create tldraw CLI
templates/ # Starter templates for different frameworks
Uses lazyrepo for incremental builds with caching:
yarn buildbuilds only what changed- Workspace dependencies handled automatically
- Caching based on file inputs/outputs
- Parallel execution where possible
TypeScript
- Uses workspace references for fast incremental compilation
- Run
yarn typecheckbefore commits - API surface validated with Microsoft API Extractor
Monorepo management
- Yarn workspaces with berry (yarn 4.x)
- Use
yarnnotnpm- packageManager field enforces this - Dependencies managed at workspace level where possible
Asset management
- Icons, fonts, translations in
/assets(managed centrally) - Run
yarn refresh-assetsafter asset changes - Assets bundled into packages during build
- Automatic optimization and deduplication
Example development
- Main development happens in
apps/examples - Examples showcase SDK capabilities
- See
apps/examples/writing-examples.mdfor guidelines
Custom shapes
- Create ShapeUtil class extending base ShapeUtil
- Implement required methods (getGeometry, component, indicator)
- Register in editor via shapeUtils prop
Custom tools
- Create StateNode class with tool logic
- Define state machine with onEnter/onExit/event handlers
- Register in editor via tools prop
UI customization
- Every tldraw UI component can be overridden
- Pass custom components via
componentsprop - See existing components for patterns
With external apps
- Import CSS:
import 'tldraw/tldraw.css'(full) orimport '@tldraw/editor/editor.css'(editor only) - Requires React 18+ and modern bundler
- Support for Vite, Next.js, and other React frameworks
Collaboration
- Use @tldraw/sync for multiplayer
- WebSocket-based real-time synchronization
- See templates/sync-cloudflare for implementation example
Licensing
- SDK has "Made with tldraw" watermark by default
- Business license removes watermark
- See tldraw.dev for licensing details
Sentence case for titles and headings
- Always use sentence case for titles, headings, and labels (NOT Title Case)
- Examples:
- ✅ "Database configuration"
- ❌ "Database Configuration"
- ✅ "Real-time updates"
- ❌ "Real-Time Updates"
- ✅ "Custom shapes"
- ❌ "Custom Shapes"
- Exception: Proper nouns, acronyms, and class/component names remain capitalized
- ✅ "PostgreSQL database"
- ✅ "WebSocket connections"
- ✅ "NodeShapeUtil implementation"
- This applies to:
- Markdown headers (##, ###, etc.)
- Bold labels in lists (Label:)
- Documentation titles
- Code comments describing features
- CONTEXT.md files
Do what has been asked; nothing more, nothing less. NEVER create files unless they're absolutely necessary for achieving your goal. ALWAYS prefer editing an existing file to creating a new one. NEVER proactively create documentation files (*.md) or README files. Only create documentation files if explicitly requested by the User.
When writing examples, be sure to read the ./apps/examples/writing-examples.md file for proper example patterns and conventions.