templates/sync-cloudflare/README.md
This is a production-ready backend for tldraw sync.
When a user opens a room, they connect via Workers to a durable object. Each durable object is like its own miniature server. There's only ever one for each room, and all the users of that room connect to it. When a user makes a change to the drawing, it's sent via a websocket connection to the durable object for that room. The durable object applies the change to its in-memory copy of the document, and broadcasts the change via websockets to all other connected clients. On a regular schedule, the durable object persists its contents to an R2 bucket. When the last client leaves the room, the durable object will shut down.
Static assets like images and videos are too big to be synced via websockets and a durable object. Instead, they're uploaded to workers which store them in the same R2 bucket as the rooms. When they're downloaded, they're cached on cloudflare's edge network to reduce costs and make serving them faster.
To install dependencies, run yarn. To start a local development server, run yarn dev. This will
start a vite dev server running both your application frontend, and the
cloudflare workers backend via the cloudflare vite
plugin. The app & server should now be
running at http://localhost:5137.
The backend worker is under worker, and is split across several files:
worker/worker.ts: the main entrypoint to the worker, defining each
route available.worker/TldrawDurableObject.ts: the sync durable object.
An instance of this is created for every active room. This exposes a
TLSocketRoom over websockets, and
periodically saves room data to R2.worker/assetUploads.ts: uploads, downloads, and caching for
static assets like images and videos.worker/bookmarkUnfurling.ts: extract URL metadata for bookmark shapes.The frontend client is under client:
client/App.tsx: the main client <App /> component. This connects our
sync backend to the <Tldraw /> component, wiring in assets and bookmark previews.
client/multiplayerAssetStore.tsx: how does the client
upload and retrieve assets like images & videos from the worker?
client/getBookmarkPreview.tsx: how does the client fetch
bookmark previews from the worker?
To add support for custom shapes, see the tldraw sync custom shapes docs.
If you already have an app using tldraw and want to use the system in this repo, you can copy and paste the relevant parts to your own app.
To add the server to your own app, copy the contents of the worker folder and
./wrangler.toml into your app. Add the dependencies from
package.json. You can run the worker using wrangler dev in the same folder as
./wrangler.toml.
To point your existing client at the server defined in this repo, copy
client/multiplayerAssetStore.tsx and
client/getBookmarkPreview.tsx into your app. Then, adapt the
code from client/App.tsx to your own app. Adapt the /api/ URLs used in each
of these files to point at your new wrangler dev server.
To deploy this example, you'll need to create a cloudflare account and create an R2 bucket to store
your data. Update bucket_name = 'tldraw-content' in wrangler.toml with the
name of your new bucket.
To actually deploy the app, first create a production build using yarn build. Then, run yarn wrangler deploy. This will deploy the backend worker along with the frontend app to cloudflare.
This should give you a workers.dev URL, but you can also configure a custom
domain.
This project is provided under the MIT license found here. The tldraw SDK is provided under the tldraw license.
Copyright (c) 2024-present tldraw Inc. The tldraw name and logo are trademarks of tldraw. Please see our trademark guidelines for info on acceptable usage.
You can find tldraw on npm here.
Please see our contributing guide. Found a bug? Please submit an issue.
Have questions, comments or feedback? Join our discord. For the latest news and release notes, visit tldraw.dev.
Find us on Twitter/X at @tldraw.