tldraw/tldraw
apps/dotcom
Active contributors: Steve Ruiz, Mitja Bezenšek, Mime Čuvalo, Max Drake, David Sheldrick
Purpose
apps/dotcom/ is everything that runs at https://tldraw.com: the React Router single-page app, the Cloudflare workers that back it, and the Zero view-syncer that replicates app-state from Postgres to clients.
Directory layout
apps/dotcom/
├── README.md
├── snapshot-state.sh
├── restore-state.sh
├── wait-for-migrations.sh
├── client/ # the SPA
├── sync-worker/ # the multiplayer server
├── asset-upload-worker/ # asset uploads → R2
├── image-resize-worker/ # image variant serving
├── tldrawusercontent-worker/ # serves user content
└── zero-cache/ # Zero view-syncer (Fly.io)Client
apps/dotcom/client/ is a Vite-built React app with React Router (src/routes.tsx, src/routeDefs.ts) and Sentry instrumentation. The two main areas:
- Anonymous editor. The classic
tldraw.com/r/<roomId>whiteboard. - tla (tldraw app). A signed-in area at
apps/dotcom/client/src/tla/with folders, file management, sharing, and account settings. "tla" is short for "tldraw app".
Major sub-folders:
apps/dotcom/client/src/
├── main.tsx
├── routes.tsx
├── routeDefs.ts
├── routes.test.tsx
├── components/ # app-level React components
├── pages/ # route components
├── hooks/
├── utils/
├── tla/ # signed-in area (folders, files, sharing)
├── assets/
└── app.d.tsThe client uses the SDK via <Tldraw />, customizes it through the override system (packages/tldraw/src/lib/ui/overrides.ts), and connects to multiplayer via useSync from @tldraw/sync pointing at apps/dotcom/sync-worker/.
Workers
The dotcom backend is a fleet of Cloudflare Workers, each its own workspace.
sync-worker
apps/dotcom/sync-worker/ is the production multiplayer server. It hosts TLSocketRoom instances inside Durable Objects, persists snapshots to R2, and uses sqlite (in the DO) for tombstone tracking. Configured via wrangler.toml. Reads/writes dotcom-shared types so the client knows the message format.
asset-upload-worker
Handles uploaded image/video blobs from the canvas. Stores in R2 and returns asset URLs.
image-resize-worker
Serves resized image variants on demand (canvas needs different sizes for different zoom levels). Cached at the edge.
tldrawusercontent-worker
Serves user-generated content under a separate domain to isolate untrusted content from the main app domain.
zero-cache
apps/dotcom/zero-cache/ runs the Zero view-syncer on Fly.io. It replicates the Postgres app database (folders, file metadata, sharing) to clients in near real-time. Two roles deploy independently:
- replication-manager — pulls Postgres replication events.
- view-syncer — fans out per-client views.
Each has its own flyio-*.template.toml config (these are also among the most-changed files in the last 90 days). The wait-for-migrations.sh script in apps/dotcom/ ensures DB migrations run before zero-cache starts in dev.
How it works
graph TB
User -->|HTTPS| Client[apps/dotcom/client]
Client -->|wss://| SyncWorker[apps/dotcom/sync-worker]
Client -->|HTTPS| AssetUpload[asset-upload-worker]
Client -->|HTTPS| ImageResize[image-resize-worker]
Client -->|HTTPS| UserContent[tldrawusercontent-worker]
Client -->|sync| ZeroCache[zero-cache view-syncer]
SyncWorker -->|R2| R2[Cloudflare R2]
SyncWorker -->|sqlite in DO| DO[Durable Object SQLite]
ZeroCache -->|replication| Postgres[(Postgres)]
AssetUpload -->|R2| R2
ImageResize -->|R2| R2The split between room state (snapshots in R2 + DO sqlite, served by sync-worker) and app state (folders, files, sharing in Postgres, served by zero-cache) is deliberate: room state is large and mutates many times per second; app state is small and mutates rarely.
Deployments
GitHub Actions:
.github/workflows/deploy-dotcom.yml— main rolling deploy..github/workflows/staging-e2e.yml— staging environment Playwright tests..github/workflows/staging-cleanup-daily.yml..github/workflows/trigger-dotcom-hotfix.yml..github/workflows/trigger-production-build.yml.
internal/scripts/deploy-dotcom.ts (one of the most-touched files in the last 90 days) is the orchestrator. The Sentry release name is computed in apps/dotcom/client/sentry-release-name.ts.
Integration points
- Imports.
tldraw,@tldraw/sync,@tldraw/sync-core,@tldraw/store,dotcom-shared,worker-shared. - External services. Cloudflare (Workers, Durable Objects, R2, KV), Fly.io (zero-cache), Postgres, Sentry, Vercel-style preview deploys.
Entry points for modification
- A new dotcom feature. Most lives under
apps/dotcom/client/src/tla/(signed-in) orapps/dotcom/client/src/components/(anon). - A new sync behavior. Usually a
sync-corechange first, then plumbed throughsync-worker. - A new asset type. Touch
asset-upload-workeranddotcom-shared.
Related
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.