UseSyncOptions
See source codeTable of contents
Configuration options for the useSync hook to establish multiplayer collaboration.
This interface defines the required and optional settings for connecting to a multiplayer server, managing user presence, handling assets, and customizing the collaboration experience.
interface UseSyncOptions {}
Example
const syncOptions: UseSyncOptions = {
uri: 'wss://myserver.com/sync/room-123',
assets: myAssetStore,
userInfo: {
id: 'user-1',
name: 'Alice',
color: '#ff0000',
},
getUserPresence: (store, user) => ({
userId: user.id,
userName: user.name,
cursor: getCursorPosition(),
}),
}
Properties
assets
Asset store implementation for handling file uploads and storage.
Required for production applications to handle images, videos, and other media efficiently. Without an asset store, files are stored inline as base64, which causes performance issues with large files.
The asset store must implement upload (for new files) and resolve (for displaying existing files) methods. For prototyping, you can use but this is not recommended for production.
assets: TLAssetStore
Example
const myAssetStore: TLAssetStore = {
upload: async (asset, file) => {
const url = await uploadToCloudStorage(file)
return { src: url }
},
resolve: (asset, context) => {
return getOptimizedUrl(asset.src, context)
},
}
uri
The WebSocket URI of the multiplayer server for real-time synchronization.
Must include the protocol (wss:// for secure, ws:// for local development). HTTP/HTTPS URLs will be automatically upgraded to WebSocket connections.
Can be a static string or a function that returns a URI (useful for dynamic authentication tokens or room routing). The function is called on each connection attempt, allowing for token refresh and dynamic routing.
Reserved query parameters sessionId
and storeId
are automatically added
by the sync system and should not be included in your URI.
uri: (() => Promise<string> | string) | string
Example
// Static URI
uri: 'wss://myserver.com/sync/room-123'
// Dynamic URI with authentication
uri: async () => {
const token = await getAuthToken()
return `wss://myserver.com/sync/room-123?token=${token}`
}
userInfo
User information for multiplayer presence and identification.
Can be a static object or a reactive signal that updates when user information changes. The presence system automatically updates when reactive signals change, allowing real-time user profile updates.
Should be synchronized with the userPreferences
prop of the main
Tldraw component for consistent user experience. If not provided,
defaults to localStorage-based user preferences.
userInfo?: Signal<TLPresenceUserInfo> | TLPresenceUserInfo
Example
// Static user info
userInfo: { id: 'user-123', name: 'Alice', color: '#ff0000' }
// Reactive user info
const userSignal = atom('user', { id: 'user-123', name: 'Alice', color: '#ff0000' })
userInfo: userSignal
Methods
getUserPresence
A reactive function that returns a TLInstancePresence object.
This function is called reactively whenever the store state changes and determines what presence information to broadcast to other clients. The result is synchronized across all connected clients for displaying cursors, selections, and other collaborative indicators.
If not provided, uses the default implementation which includes standard cursor position and selection state. Custom implementations allow you to add additional presence data like current tool, view state, or custom status.
See getDefaultUserPresence for the default implementation of this function.
Example
getUserPresence: (store, user) => {
return {
userId: user.id,
userName: user.name,
cursor: { x: 100, y: 200 },
currentTool: 'select',
isActive: true,
}
}
Parameters
Name | Description |
---|---|
| The current TLStore |
| The current user information |
Returns
null | TLPresenceStateInfo
Presence state to broadcast to other clients, or null to hide presence
onCustomMessageReceived
Handler for receiving custom messages sent through the multiplayer connection.
Use this to implement custom communication channels between clients beyond the standard shape and presence synchronization. Messages are sent using the TLSyncClient's sendMessage method.
Example
onCustomMessageReceived: (data) => {
if (data.type === 'chat') {
displayChatMessage(data.message, data.userId)
}
}
Parameters
Name | Description |
---|---|
|
The custom message data received from another client |
Returns
void