API Reference - @liveblocks/client
@liveblocks/client
provides you with JavaScript bindings for our realtime
collaboration APIs, built on top of WebSockets. Read our
getting started guides to learn more.
createClient
Creates a client that allows you to connect to Liveblocks servers.
You must define either authEndpoint
or publicApiKey
. Resolver functions
should be placed inside here, and a number of other options are available.
- clientClient
Returns a Client, used for connecting to Liveblocks.
- authEndpoint
The URL of your back end’s authentication endpoint as a string, or an async callback function that returns a Liveblocks token result. Either
authEndpoint
orpublicApikey
are required. Learn more about using a URL string and using a callback. - publicApiKeystring
The public API key taken from your project’s dashboard. Generally not recommended for production use. Either
authEndpoint
orpublicApikey
are required. Learn more. - throttlenumberDefault is 100
The throttle time between WebSocket messages in milliseconds, a number between
16
and1000
is allowed. Using16
means your app will update 60 times per second. Learn more. - preventUnsavedChangesbooleanDefault is false
When set, navigating away from the current page is prevented while Liveblocks is still synchronizing local changes. Learn more.
- lostConnectionTimeoutnumberDefault is 5000
After a user disconnects, the time in milliseconds before a
"lost-connection"
event is fired. Learn more. - backgroundKeepAliveTimeoutnumber
The time before an inactive WebSocket connection is disconnected. This is disabled by default, but setting a number will activate it. Learn more.
- resolveUsers
A function that resolves user information in Comments, Text Editor, and Notifications. Return an array of
UserMeta["info"]
objects in the same order they arrived. Learn more. - resolveRoomsInfo
A function that resolves room information in Notifications. Return an array of
RoomInfo
objects in the same order they arrived. Learn more. - resolveGroupsInfo
A function that resolves group information in Comments and Text Editor. Return an array of
GroupInfo
objects in the same order they arrived. Learn more. - resolveMentionSuggestions
A function that resolves mention suggestions in Comments and Text Editor. Return an array of user IDs or mention objects. Learn more.
- polyfills
Place polyfills for
atob
,fetch
, andWebSocket
inside here. Useful when using a non-browser environment, such as Node.js or React Native. - largeMessageStrategyDefault is "default"
How to handle WebSocket messages that are larger than the maximum message size. Can be set to one of these values:
"default"
Don’t send anything, but log the error to the console and notify useErrorListener."split"
Break the message up into chunks each of which is smaller than the maximum message size. Beware that using"split"
will sacrifice atomicity of changes! Depending on your use case, this may or may not be problematic."experimental-fallback-to-http"
Try sending the update over HTTP instead of WebSockets (experimental).
- unstable_streamDatabooleanDefault is false
Experimental. Stream the initial Storage content over HTTP, instead of waiting for a large initial WebSocket message to be sent from the server.
createClient with public key
When creating a client with a public key, you don’t need to set up an authorization endpoint. We only recommend using a public key when prototyping, or on public landing pages, as it makes it possible for end users to access any room’s data. You should instead use an auth endpoint.
createClient with auth endpoint
If you are not using a public key, you need to set up your own authEndpoint
.
Please refer to our Authentication guide.
createClient with auth endpoint callback
If you need to add additional headers or use your own function to call your
endpoint, authEndpoint
can be provided as a custom callback. You should return
the token created with
Liveblocks.prepareSession
or liveblocks.identifyUser
,
learn more in authentication guide.
room
is the room ID that the user is connecting to. When using
Notifications, room
can be undefined
, as the client is requesting a token that grants access to
multiple rooms, rather than a specific room.
Fetch your endpoint
Here’s an example of fetching your API endpoint at /api/liveblocks-auth
within
the callback.
Token details
You should return the token created with
Liveblocks.prepareSession
or liveblocks.identifyUser
.
These are the values the functions can return.
- A valid token, it returns a
{ "token": "..." }
shaped response. - A token that explicitly forbids access, it returns an
{ "error": "forbidden", "reason": "..." }
shaped response. If this is returned, the client will disconnect and won’t keep trying to authorize.
Any other error will be treated as an unexpected error, after which the client will retry the request until it receives either 1. or 2.
WebSocket throttle
By default, the client throttles the WebSocket messages sent to one every 100
milliseconds, which translates to 10 updates per second. It’s possible to
override that configuration with the throttle
option with a value between 16
and 1000
milliseconds.
This option is helpful for smoothing out realtime animations in your application, as you can effectively increase the framerate without using any interpolation. Here are some examples with their approximate frames per second (FPS) values.
Prevent users losing unsaved changes
Liveblocks usually synchronizes milliseconds after a local change, but if a user
immediately closes their tab, or if they have a slow connection, it may take
longer for changes to synchronize. Enabling preventUnsavedChanges
will stop
tabs with unsaved changes closing, by opening a dialog that warns users. In
usual circumstances, it will very rarely trigger.
More specifically, this option triggers when:
- There are unsaved changes after calling any hooks or methods, in all of our products.
- There are unsaved changes in a Text Editor.
- There’s an unsubmitted comment in the Composer.
- The user has made changes and is currently offline.
Internally, this option uses the beforeunload event.
Lost connection timeout
If you’re connected to a room and briefly lose connection, Liveblocks will reconnect automatically and quickly. However, if reconnecting takes longer than usual, for example if your network is offline, then the room will emit an event informing you about this.
How quickly this event is triggered can be configured with the
lostConnectionTimeout
setting, and it takes a number in milliseconds.
lostConnectionTimeout
can be set between 1000
and 30000
milliseconds. The
default is 5000
, or 5 seconds.
You can listen to the event with room.subscribe("lost-connection")
. Note
that this also affects when others
are reset to an empty array after a
disconnection. This helps prevent temporary flashes in your application as a
user quickly disconnects and reconnects. For a demonstration of this behavior,
see our connection status example.
Background keep-alive timeout
By default, Liveblocks applications will maintain an active WebSocket connection
to the Liveblocks servers, even when running in a browser tab that’s in the
background. However, if you’d prefer for background tabs to disconnect after a
period of inactivity, then you can use backgroundKeepAliveTimeout
.
When backgroundKeepAliveTimeout
is specified, the client will automatically
disconnect applications that have been in an unfocused background tab for at
least the specified time. When the browser tab is refocused, the client will
immediately reconnect to the room and synchronize the document.
backgroundKeepAliveTimeout
accepts a number in milliseconds—we advise using a
value of at least a few minutes, to avoid unnecessary disconnections.
resolveUsers
Comments and Text Editor store user IDs in their system, but no other user information. To display user information in Comments, Text Editor, and Notifications components, such as a user’s name or avatar, you need to resolve these IDs into user objects. This function receives a list of user IDs and you should return a list of user objects of the same size, in the same order.
User IDs are automatically resolved in batches with a maximum of 50 users per batch to optimize performance and prevent overwhelming your user resolution function.
The name and avatar you return are rendered in
Thread
components.
User objects
The user objects returned by the resolver function take the shape of
UserMeta["info"]
, which contains name
and avatar
by default. These two
values are optional, though if you’re using the
Comments default components,
they are necessary. Here’s an example of userIds
and the exact values
returned.
You can also return custom information, for example, a user’s color
:
Accessing user data in React
You can access any values set within resolveUsers
with the
useUser
hook.
resolveRoomsInfo
When using
Notifications with
Comments, room IDs will be used to
contextualize notifications (e.g. “Chris mentioned you in room-id”) in the
InboxNotification
component. To replace room IDs with more fitting names (e.g. document names,
“Chris mentioned you in Document A”), you can provide a resolver function to
the resolveRoomsInfo
option in createClient
.
This resolver function will receive a list of room IDs and should return a list of room info objects of the same size and in the same order.
In addition to the room’s name, you can also provide a room’s URL as the url
property. If you do so, the
InboxNotification
component will automatically use it. It’s possible to use an inbox
notification’s roomId
property to construct a room’s URL directly in React and
set it on
InboxNotification
via href
, but the room ID might not be enough for you to construct the URL ,
you might need to call your backend for example. In that case, providing it via
resolveRoomsInfo
is the preferred way.
resolveGroupsInfo
When using group mentions with Comments
and Text Editor, group IDs will be used
instead of user IDs. Similarly to resolveUsers
,
you can provide a resolver function to the resolveGroupsInfo
option in
createClient
to assign information like names and avatars to
group IDs.
Accessing group info in React
You can access any values set within resolveGroupsInfo
with the
useGroupInfo
hook.
resolveMentionSuggestions
To enable creating mentions in Comments
and Text Editor, you can provide a
resolver function to the resolveMentionSuggestions
option in
createClient
. These mentions will be displayed in the
Composer
component and in
text editors.
This resolver function will receive the mention currently being typed (e.g. when
writing “@jane”, text
will be jane
) and should return a list of user IDs
matching that text. This function will be called every time the text changes but
with some debouncing.
Group mentions
To support group mentions in Comments and Text Editor, you can return a list of mention objects instead of user IDs to suggest a mix of user and group mentions.
The mention objects specify which kind of mention it is, the ID to mention (user ID or group ID), etc.
createClient for Node.js
To use @liveblocks/client
in Node.js, you need to provide WebSocket
and
fetch
polyfills. As polyfills, we recommend installing ws
and
node-fetch
.
Then, pass them to the createClient
polyfill option as below.
Note that node-fetch
v3+
does not support CommonJS.
If you are using CommonJS, downgrade node-fetch
to v2.
createClient for React Native
To use @liveblocks/client
with React Native, you
need to add an atob
polyfill. As a polyfill, we recommend installing
base-64
.
Then you can pass the decode
function to our atob
polyfill option when you
create the client.
Client
Client returned by createClient
which allows you to connect to Liveblocks
servers in your application, and enter rooms.
Client.enterRoom
Enters a room and returns both the local Room
instance, and a leave
unsubscribe function. The authentication endpoint is called as soon as you call
this function. Used for setting initial Presence
and initial Storage values.
Note that it’s possible to add types to your room.
- roomRoom<Presence, Storage, UserMeta, RoomEvent>
A Room, used for building your Liveblocks application. Learn more about typing your room.
- leave() => void
A function that’s used to leave the room and disconnect.
- roomIdstringRequired
The ID of the room you’re connecting to.
- options.initialPresenceJsonObject
The initial Presence of the user entering the room. Each user has their own presence, and this is readable for all other connected users. A user’s Presence resets every time they disconnect. This object must be JSON-serializable. Learn more.
- options.initialStorageLsonObject
The initial Storage structure for the room when it’s joined for the first time. This is only set a single time, when the room has not yet been populated. This object must contain conflict-free live structures. Learn more.
- options.autoConnectbooleanDefault is true
Whether the room immediately connects to Liveblocks servers.
Setting initial Presence
Presence is used for storing temporary user-based values, such as a user’s
cursor coordinates, or their current selection. Each user has their own
presence, and this is readable for all other connected users. Set your initial
Presence value by using initialPresence
.
Each user’s Presence resets every time they disconnect, as this is only meant
for temporary data. Any JSON-serializable object is allowed (the JsonObject
type).
Setting initial Storage
Storage is used to store permanent data that’s used in your application, such as
shapes on a whiteboard, nodes on a flowchart, or text in a form. The first time
a room is entered, you can set an initial value by using initialStorage
.
initialStorage
is only read and set a single time, unless a new top-level
property is added.
If a new top-level property is added to initialStorage
, the next time a user
connects, the new property will be created. Other properties will be unaffected.
Any
conflict-free live structures
and JSON-serializable objects are allowed (the LsonObject
type).
Client.getRoom
Gets a room by its ID. Returns null
if client.enterRoom
has not been
called previously.
It’s unlikely you’ll need this API if you’re using the newer
client.enterRoom
API. Note that it’s possible to
add types to your room.
- roomRoom<Presence, Storage, UserMeta, RoomEvent> | null
A Room, used for building your Liveblocks application. Returns
null
if the room has not yet been joined by the current client. Learn more about typing your room.
- roomIdstringRequired
The ID of the room you’re connecting to.
Client.getSyncStatus
Gets the current Liveblocks synchronization status.
- returns"synchronizing" | "synchronized"
Will be
"synchronizing"
if there are any local changes to any part of Liveblocks that still need to be acknowledged by the server. Will be"synchronized"
when all local changes have been persisted.
Client.logout
Purges any auth tokens from the client’s memory. If there are any rooms that are still connected, they will be forced to reauthorize.
When to logout
Use this function if you have a single page application (SPA) and you wish to
log your user out, and reauthenticate them. This is a way to update your user’s
info
after a connection has begun.
AI Copilots
defineAiTool
Create a custom tool for your AI copilot to use. Defining tools allow the AI copilot to look up information on-demand, render your own components based on the tool’s arguments, or perform actions in your application on behalf of the current user, such as creating content, updating the application state, or interacting with external services.
- toolAiOpaqueToolDefinition
An AI tool.
- descriptionstring
A clear description of what the tool does. Used by AI to understand when to call this tool.
- parametersJSONSchema7
JSON Schema defining the tool’s input parameters. The AI will validate arguments against this schema.
- enabledboolean
Whether this tool should be enabled. When set to
false
, the tool will not be made available to the AI copilot for any new/future chat messages, but will still allow existing tool invocations to be rendered that are part of the historic chat record. Defaults to true. - executefunction
Async function that performs the tool’s action. Receives validated arguments and execution context, returns structured data. See implementing the tool call via
execute
. - renderfunction
React component function that renders the tool’s UI during different execution stages. See tool call rendering stages.
Tools can be registered globally with
RegisterAiTool
or
passed directly to AiChat
.
Tool call rendering stages
Rendering a tool call can be done before the tool call is executed, which allows you to display a UI during its entire lifecycle. The tool call stages are:
receiving
(since 3.4) The tool call is being received and its args are being streamed in. During this stage, you can accesspartialArgs
to display a UI while the tool call arguments are still being constructed, but before the tool call is executed.executing
The tool call is currently executing, or is ready to be. In this stage, theargs
are fully known, but the result of the tool call is not known yet.executed
The tool call has been executed, and the result is known. This happens after yourexecute
function was run, or after you calledrespond()
insiderender
. In this stage, theresult
object will be available.
The render component will automatically re-render when its stage changes.
Implementing tool calls
When you implement a tool call, use one of these combinations:
- Implement
execute
andrender
- Implement only
execute
, but norender
- Implement only
render
, but make sure to eventually callrespond()
Implementing your tool call via execute
If you implement the execute
function, this function will automatically be
invoked when the tool call gets made. The return value of this function will be
the result that will be passed back to the AI copilot.
{ data: any, description?: string }
The data to return in case of success.data
must be a legal JSON value. Providing a description is optional. If you provide a description, it will be passed to the AI copilot to help it understand the returned data or to provide follow-up instructions for how to respond to this tool result.{ error: string }
The error message in case the tool call failed to execute.{ cancel: true | string }
If the tool call should be cancelled. You can optionally provide a cancel reason as an instruction to the AI copilot.
The returned value can be observed in the render
method, through the result
param:
If you do not implement render
alongside execute
, the tool call will still
be executed, but no UI will be displayed. The result will still be passed back
to the AI copilot.
Implementing your tool call via render
Sometimes you may not want to immediately execute the tool call. This is most
common to build a Human-in-the-Loop (HITL) style UI where you want the user to
confirm or correct the tool call’s behavior. In these scenarios, you do not want
to implement execute
. Instead, you could display any UI, as long as you
eventually call the respond
function that is provided to render
’s props.
In this example, until the Confirm button is clicked, the AI chat will remain in “executing” stage, awaiting the result of this tool call.
This example is for illustrative purposes only. In practice, using our
AiTool.Confirmation
tool is preferred for building confirm/cancel flows.
Like with the execute
function, the respond
function should be called with a
value of this shape:
{ data: any, description?: string }
The data to return in case of success.data
must be a legal JSON value. Providing a description is optional. If you provide a description, it will be passed to the AI copilot to help it understand the returned data or to provide follow-up instructions for how to respond to this tool result.{ error: string }
The error message in case the tool call failed to execute.{ cancel: true | string }
If the tool call should be cancelled. You can optionally provide a cancel reason as an instruction to the AI copilot.
Handling different tool call stages
You can handle all three stages of a tool call in your render function to provide a smooth user experience during tool call streaming and execution:
In this example, the tool arguments stream in progressively during the
receiving
stage, causing multiple re-renders as each field appears:
- 1st render:
{ stage: "receiving", partialArgs: {} }
- 2nd render:
{ stage: "receiving", partialArgs: { origin: "New York" } }
- 3rd render:
{ stage: "receiving", partialArgs: { origin: "New York", destination: "London" } }
- 4th render:
{ stage: "receiving", partialArgs: { origin: "New York", destination: "London", departureDate: "2024-12-15" } }
- 5th render:
{ stage: "receiving", partialArgs: { ..., passengers: [] } }
- 6th render:
{ stage: "receiving", partialArgs: { ..., passengers: [{ name: "John" }] } }
- 7th render:
{ stage: "receiving", partialArgs: { ..., passengers: [{ name: "John", age: 3 }] } }
- 8th render:
{ stage: "receiving", partialArgs: { ..., passengers: [{ name: "John", age: 30 }] } }
- Final render:
{ stage: "executing", args: { /* complete object */ } }
This demonstrates how each field and nested property appears incrementally, providing real-time feedback to users as the AI constructs the tool call arguments.
Arguments are streamed in forward-only order. Once a field begins appearing, all
previous fields are complete and won’t be modified. You’ll never see
{ origin: "New York", destination: "London" }
followed by
{ origin: "San Francisco", destination: "London" }
, but you might see
{ origin: "New" }
then { origin: "New York" }
then
{ origin: "New York", destination: "London" }
.
Room
Room returned by client.enterRoom
(or client.getRoom
).
Room.getPresence
Return the current user’s Presence. Presence is used to store custom properties on each user that exist until the user disconnects. An example use would be storing a user’s cursor coordinates.
Presence is set with updatePresence
and can be typed
when you enter a room. The example above is using
the following type:
- presenceTPresence
An object holding the Presence value for the currently connected user. Presence is set with
updatePresence
. Will always be JSON-serializable.TPresence
is thePresence
type you set yourself, learn more.
Room.updatePresence
Updates the current user’s Presence. Only pass the properties you wish to update—any changes will be merged into the current presence. The entire presence object will not be replaced.
- updateTPresenceRequired
The updated Presence properties for the current user inside an object. The user’s entire Presence object will not be replaced, instead these properties will be merged with the existing Presence. This object must be JSON-serializable.
- options.addToHistorybooleanDefault is false
Adds Presence values to the history stack, meaning using undo and redo functions will change them. Learn more.
Add Presence to history
By default, Presence values are not added to history. However, using the
addToHistory
option will add items to the undo/redo stack.
See room.history
for more information.
Room.getOthers
Returns an array of currently connected users in the room. Returns a
User
object for each user. Note that you can also subscribe to
others using Room.subscribe("others")
.
- othersUser<Presence, UserMeta>[]
An array holding each connected user’s
User
object.User
contains the current user’s Presence value, along with other information. Presence is set withupdatePresence
. Returns an empty array when no other users are currently connected. Will always be JSON-serializable.
Room.broadcastEvent
Broadcast an event to other users in the Room. Events broadcast to the room can
be listened to with Room.subscribe("event")
. Takes a custom event payload
as first argument. Should be serializable to JSON.
- eventTRoomEventRequired
The event to broadcast to every other user in the room. Must be JSON-serializable.
TRoomEvent
is theRoomEvent
type you set yourself, learn more. - options.shouldQueueEventIfNotReadybooleanDefault is false
Queue the event if the connection is currently closed, or has not been opened yet. We’re not sure if we want to support this option in the future so it might be deprecated to be replaced by something else. Learn more.
Receiving an event
To receive an event, use Room.subscribe("event")
. The user
property
received on the other end is the sender’s User
instance.
We recommend using a property such as type
, so that it’s easy to distinguish
between different events on the receiving end.
Typing multiple events
When defining your types, you can pass a RoomEvent
type
in your config file to receive type hints in your app. To define multiple
different custom events, use a union.
Broadcasting an event when disconnected
By default, broadcasting an event is a “fire and forget” action. If the sending
client is not currently connected to a room, the event is simply discarded. When
passing the shouldQueueEventIfNotReady
option, the client will queue up the
event, and only send it once the connection to the room is (re)established.
Room.getSelf
Gets the current User
. Returns null
if the client is not yet
connected to the room.
- userUser<Presence, UserMeta> | null
Returns the current
User
. Returnsnull
if the client is not yet connected to the room.
Here’s an example of a full return value, assuming Presence
and UserMeta
have been set.
Room.getStatus
Gets the current WebSocket connection status of the room. The possible value
are: initial
, connecting
, connected
, reconnecting
, or disconnected
.
- status"initial" | "connecting" | "connected" | "reconnecting" | "disconnected"
Returns the room’s current connection status. It can return one of five values:
"initial"
The room has not attempted to connect yet."connecting"
The room is currently authenticating or connecting."connected"
The room is connected."reconnecting"
The room has disconnected, and is trying to connect again."disconnected"
The room is disconnected, and is no longer attempting to connect.
Room.getStorageStatus
Get the Storage status. Use this to tell whether Storage has been synchronized with the Liveblocks servers.
- status"not-loaded" | "loading" | "synchronizing" | "synchronized"
The current room’s Storage status.
status
can be one of four types."not-loaded
Storage has not been loaded yet asroom.getStorage
has not been called."loading"
Storage is currently loading for the first time."synchronizing"
Local Storage changes are currently being synchronized."synchronized"
Local Storage changes have been synchronized.
Room.subscribe(storageItem)
Subscribe to updates on a particular storage item, and takes a callback function
that’s called when the storage item is updated. The Storage root
is a
LiveObject
, which means you can subscribe to this, as well as other live
structures. Returns an unsubscribe function.
- unsubscribe() => void
Unsubscribe function. Call it to cancel the subscription.
- storageItemL extends (LiveObject | LiveMap | LiveList)Required
The
LiveObject
,LiveMap
, orLiveList
which is being subscribed to. Each time the structure is updated, the callback is called. - callback(node: L) => voidRequired
Function that’s called when
storageItem
updates. Returns the updated storage structure. - options.isDeepboolean
Subscribe to both
storageItem
and its children. The callback function will be passed a list of updates instead of just the new Storage item. Learn more.
Typing Storage
To type the Storage values you receive, make sure to set your Storage
type.
The type received in the callback will match the type passed. Learn more under typing your room.
Subscribe to any live structure
You can subscribe to any live structure, be it the Storage root
, a child, or a
structure even more deeply nested.
Listening for nested changes
It’s also possible to subscribe to a Storage item and all of its children by
passing an optional isDeep
option in the third argument. In this case, the
callback will be passed a list of updates instead of just the new Storage item.
Each such update is a { type, node, updates }
object.
Using async functions
You use an async
function inside the subscription callback, though bear in
mind that the callback itself is synchronous, and there’s no guarantee the
async
function will complete before the callback is run again.
If the order of updates is imporant in your application, and it’s important to
ensure that your async
function doesn’t start before the previous one
finishes, you can use a package such as
async-mutex
to help you with
this. Using runExclusive
will effectively form a queue for all upcoming
updates, guaranteeing serial execution.
Note that this may cause a performance penalty in your application, as certain updates will be ignored.
Room.subscribe("event")
Subscribe to events broadcast by Room.broadcastEvent
. Takes a callback
that’s run when another user calls Room.broadcastEvent
. Provides the
event
along with the user
and their connectionId
of the user that sent the
message. Returns an unsubscribe function.
- unsubscribe() => void
Unsubscribe function. Call it to cancel the subscription.
- eventType"event"Required
Listen to events.
- callbackRequired
Function that’s called when another user sends an event. Receives the event, the
user
that sent the event, and theirconnectionId
. If this event was sent vialiveblocks.broadcastEvent
or the Broadcast event API,user
will benull
andconnectionId
will be-1
. Learn more
Typing events
When defining your types, you can pass a RoomEvent
type
to your config file to receive type hints in your app. To define multiple
different custom events, use a union.
Receiving events from the server
Events can be received from the server with either
liveblocks.broadcastEvent
or the
Broadcast Event API.
In events sent from the server, user
will be null
, and connectionId
will
be -1
.
Room.subscribe("my-presence")
Subscribe to the current user’s Presence. Takes a callback that is called every
time the current user presence is updated with Room.updatePresence
.
Returns an unsubscribe function.
- unsubscribe() => void
Unsubscribe function. Call it to cancel the subscription.
- eventType"my-presence"Required
Listen to the current user’s presence.
- callback(presence: TPresence) => voidRequired
Function that’s called when the current user’s Presence has updated, for example with
Room.updatePresence
. Receives the updates Presence value.
Typing Presence
To type the Presence values you receive, make sure to set your Presence type.
The type received in the callback will match the type passed. Learn more under typing your data.
Room.subscribe("others")
Subscribe to every other users’ updates. Takes a callback that’s called when a user’s Presence updates, or when they enter or leave the room. Returns an unsubscribe function.
- unsubscribe() => void
Unsubscribe function. Call it to cancel the subscription.
- eventType"others"Required
Listen to others.
- callback(others: User<Presence, UserMeta>[], event: OthersEvent) => voidRequired
Function that’s called when another user’s Presence has updated, for example with
Room.updatePresence
, or an others event has occurred. Receives an array ofUser
values for each currently connected user. Also received an object with information about the event that has triggered the update, learn more.
Typing Presence
To type the Presence values you receive, make sure to set your Presence type.
The type received in the callback will match the type passed. Learn more under typing your data.
Listening for others events
The event
parameter returns information on why the callback has just run, for
example if their Presence has updated, if they’ve just left or entered the room,
or if the current user has disconnected.
Live cursors
Here’s a basic example showing you how to render live cursors.
Room.updatePresence
is being used to update each user’s cursor position.
Check our examples page for live demos.
Room.subscribe("status")
Subscribe to WebSocket connection status updates. Takes a callback that is
called whenever the connection status changes. Possible value are: initial
,
connecting
, connected
, reconnecting
, or disconnected
. Returns an
unsubscribe function.
- unsubscribe() => void
Unsubscribe function. Call it to cancel the subscription.
- eventType"status"Required
Listen to status updates.
- callbackRequired
Function that’s called when the room’s connection status has changed. It can return one of five values:
"initial"
The room has not attempted to connect yet."connecting"
The room is currently authenticating or connecting."connected"
The room is connected."reconnecting"
The room has disconnected, and is trying to connect again."disconnected"
The room is disconnected, and is no longer attempting to connect.
When to use status
Status is a low-level API that exposes the WebSocket’s connectivity status. You
can use this, for example, to update a connection status indicator in your UI.
It would be normal for a client to briefly lose the connection and restore it
with quick connected
→ reconnecting
→ connected
status jumps.
If you’d like to let users know that there may be connectivity issues, don’t use
this API, but instead refer to Room.subscribe("lost-connection")
which was
specially built for this purpose.
Do not use this API to detect when Storage or Presence are initialized or
loaded. "Connected" does not guarantee that Storage or Presence are ready. To
detect when Storage is loaded, rely on awaiting the Room.getStorage
promise or using the Room.subscribe("storage-status")
event.
Room.subscribe("lost-connection")
A special-purpose event that will fire when a previously connected Liveblocks client has lost connection, for example due to a network outage, and was unable to recover quickly. This event is designed to help improve UX for your users, and will not trigger on short interruptions, those that are less than 5 seconds by default. The event only triggers if a previously connected client disconnects.
- unsubscribe() => void
Unsubscribe function. Call it to cancel the subscription.
- eventType"lost-connection"Required
Listen to lost connection events.
- callbackRequired
Function that’s called when a room’s lost connection event has been triggered. It can return one of three values:
"lost"
A connection has been lost for longer thanlostConnectionTimeout
."restored"
The connection has been restored again."failed"
The room has been unable to reconnect again, and is no longer trying. This may happen if a user’s network has recovered, but the room’s authentication values no longer allow them to enter.
When to use lost connection events
Lost connections events allows you to build high-quality UIs by warning your users that the application is still trying to re-establish the connection, for example through a toast notification. You may want to take extra care in the mean time to ensure their changes won’t go unsaved, or to help them understand why they’re not seeing updates made by others yet.
When this happens, this callback is called with the event lost
. Then, once the
connection restores, the callback will be called with the value restored
. If
the connection could definitively not be restored, it will be called with
failed
(uncommon).
Setting lost connection timeout
The lostConnectionTimeout
configuration option will determine how quickly
the event triggers after a connection loss occurs. By default, it’s set to
5000
ms, which is 5 seconds.
Room.subscribe("error")
Subscribe to unrecoverable room connection errors. This event will be emitted
immediately before the client disconnects and won’t try reconnecting again.
Returns an unsubscribe function. If you’d like to retry connecting, call
room.reconnect
.
- unsubscribe() => void
Unsubscribe function. Call it to cancel the subscription.
- eventType"error"Required
Listen to error events.
- callbackRequired
Function that’s called when an unrecoverable error event has been triggered.
error.code
can return one of these values:-1
Authentication error.4001
Could not connect because you don’t have access to this room.4005
Could not connect because room was full.4006
The room ID has changed.
When to use error events
You can use this event to trigger a “Not allowed” screen/dialog. It can also be helpful for implementing a redirect to another page.
When a room ID has changed
When a room ID has been changed with
liveblocks.updateRoomId
or the
Update Room ID API,
error.message
will contain the new room ID.
Room.subscribe("history")
Subscribe to the current user’s history changes. Returns an unsubscribe function.
- unsubscribe() => void
Unsubscribe function. Call it to cancel the subscription.
- eventType"history"Required
Listen to history events.
- callbackRequired
Room.subscribe("storage-status")
Subscribe to Storage status changes. Use this to tell whether Storage has been synchronized with the Liveblocks servers. Returns an unsubscribe function.
- unsubscribe() => void
Unsubscribe function. Call it to cancel the subscription.
- eventType"storage-status"Required
Listen to Storage status events.
- callbackRequired
Function that’s called when the current user’s Storage updated status have changed.
status
can be one of four types."not-loaded
- Storage has not been loaded yet as [getStorage
][] has not been called."loading"
- Storage is currently loading for the first time."synchronizing"
- Local Storage changes are currently being synchronized."synchronized"
- Local Storage changes have been synchronized
Room.batch
Batches Storage and Presence modifications made during the given function. Each modification is grouped together, which means that other clients receive the changes as a single message after the batch function has run. When undoing or redoing these changes, the entire batch will be undone/redone together instead of atomically.
- returnT
Returns the return value from the callback.
- callback() => TRequired
A callback containing every Storage and Presence notification that will be part of the batch. Cannot be an
async
function.
When to batch updates
For the most part, you don’t need to batch updates. For example, given a whiteboard application, it’s perfectly fine to update a note’s position on the board multiple times per second, in separate updates. However, should you implement a “Delete all” button, that may delete 50 notes at once, this is where you should use a batch.
This batch places each
LiveMap.delete
call
into a single WebSocket update, instead of sending multiple updates. This will
be much quicker.
Batching groups history changes
Batching changes will also group changes into a single history state.
Doesn’t work with async functions
Note that room.batch
cannot take an async
function.
Room.history
Room’s history contains functions that let you undo and redo operations made to Storage and Presence on the current client. Each user has a separate history stored in memory, and history is reset when the page is reloaded.
Add Presence to history
By default, history is only enabled for Storage. However, you can use the
addToHistory
option to additionally
add Presence state to history.
Room.history.undo
Reverts the last operation. It does not impact operations made by other clients, and will only undo changes made by the current client.
Room.history.redo
Restores the last undone operation. It does not impact operations made by other clients, and will only restore changes made by the current client.
Room.history.canUndo
Returns true or false, depending on whether there are any operations to undo. Helpful for disabling undo buttons.
- canUndoboolean
Whether there is an undo operation in the current history stack.
Room.history.canRedo
Returns true or false, depending on whether there are any operations to redo. Helpful for disabling redo buttons.
- canRedoboolean
Whether there is a redo operation in the current history stack.
Room.history.clear
Clears the undo and redo stacks for the current client. Explicitly clearing history resets the ability to undo beyond the current document state. Other clients’ histories are unaffected.
Room.history.pause
All future modifications made on the Room will be merged together to create a single history item until resume is called.
Room.history.resume
Resumes history after a pause. Modifications made on the Room are not merged into a single history item any more.
Room.connect
Connect the local room instance to the Liveblocks server. Does nothing if the room is already connecting, reconnecting or connected. We don’t recommend using this API directly.
Room.reconnect
Reconnect the local room instance to the Liveblocks server, using a new WebSocket connection.
Room.disconnect
Disconnect the local room instance from the Liveblocks server. The room instance will remain functional (for example, it will still allow local presence or storage mutations), but since it’s no longer connected, changes will not be persisted or synchronized until the room instance is reconnected again. We don’t recommend using this API directly.
Comments
Room.getThreads
Returns threads, and their associated inbox notifications and subscriptions, that are in the current room. It also returns the request date that can be used for subsequent polling. It’s possible to filter for a thread’s resolved status and using custom metadata.
- threadsThreadData[]
Threads within the current room.
- inboxNotificationsInboxNotificationData[]
Inbox notifications associated with the threads.
- subscriptionsSubscriptionData[]
Subscriptions associated with the threads.
- requestedAtDate
The request date to use for subsequent polling.
- resolvedboolean
Only return
resolved
orunresolved
threads. Learn more. - metadataPartial<ThreadMetadata>
Only return threads containing the custom metadata. Metadata is set yourself when creating a thread, for example
{ priority: "HIGH" }
. Learn more.
Filtering resolved status
You can filter threads by those that are resolved, or unresolved, by passing a
boolean
to query.resolved
.
Filtering metadata
You can define custom metadata when
creating a thread,
and the query.metadata
option allows you to return only threads that match.
You can also filter for metadata that begins with a specific string.
Room.getThreadsSince
Returns threads, and their associated inbox notifications and subscriptions,
that have been updated or deleted since the requested date. Helpful when used in
combination with Room.getThreads
to initially fetch all
threads, then receive updates later.
- threads
Threads that have been updated or deleted since the requested date.
- inboxNotifications
Inbox notifications that have been updated or deleted since the requested date.
- subscriptions
Subscriptions that have been updated or deleted since the requested date.
- requestedAtDate
The request date to use for subsequent polling.
- sinceDateRequired
Only return threads that have been updated or deleted after this date.
Room.getThread
Returns a thread and its associated inbox notification and subscription, from its ID, if it exists.
The thread ID can be retrieved from existing threads.
- threadThreadData | undefined
The requested thread, or
undefined
if it doesn’t exist. - inboxNotificationInboxNotificationThreadData | undefined
The inbox notification associated with the thread, or
undefined
if it doesn’t exist. - subscriptionSubscriptionData | undefined
The subscription associated with the thread, or
undefined
if it doesn’t exist.
- valuestringRequired
The ID of the thread you want to retrieve.
Room.createThread
Creates a thread, and its initial comment, in the current room. A comment’s body is an array of paragraphs, each containing child nodes, learn more under creating thread content.
- valueThreadData
The thread that has been created.
- bodyCommentBodyRequired
The content of the comment, see creating thread content.
- attachmentIdsstring
The IDs of the comment’s attachments.
- metadataThreadMetadata
Custom metadata to be attached to the thread, see defining thread metadata.
Creating thread content
A comment’s body is an array of paragraphs, each containing child nodes. Here’s
an example of how to construct the following simple comment body, which can be
passed to room.createThread
.
Hello world
Second paragraph!
It’s also possible to create links and mentions.
@Jody Hekla the Liveblocks website is cool!
Defining thread metadata
Custom metadata can be attached to each thread. string
, number
, and
boolean
properties are allowed.
Room.deleteThread
Deletes a thread by its ID.
- threadIdstringRequired
The ID of the thread to delete.
Room.editThreadMetadata
Edits a thread’s custom metadata. Metadata can be a string
, number
, or
boolean
. To delete an existing metadata property, set its value to null
.
- metadataThreadMetadata
The thread metadata.
- threadIdstringRequired
The ID of the thread.
- metadataPatchable<ThreadMetadata>Required
An object containing the metadata properties to update. Metadata can be a
string
,number
, orboolean
. To delete an existing metadata property, set its value tonull
.
Room.markThreadAsResolved
Marks a thread as resolved.
- threadIdstringRequired
The ID of the thread to resolve.
Room.markThreadAsUnresolved
Marks a thread as unresolved.
- threadIdstringRequired
The ID of the thread to resolve.
Room.subscribeToThread
Subscribes the user to a thread, meaning they will receive inbox notifications when new comments are posted.
- valueSubscriptionData
The thread’s subscription.
- threadIdstringRequired
The ID of the thread to subscribe to.
Replacing room-level subscriptions
Subscribing will replace any existing subscription for the current thread set at room-level. This value can also be overridden by a room-level call that is run afterwards.
Room.unsubscribeFromThread
Unsubscribes the user from a thread, meaning they will no longer receive inbox notifications when new comments are posted.
- threadIdstringRequired
The ID of the thread to unsubscribe from.
Replacing room-level unsubscriptions
Unsubscribing will replace any existing unsubscription for the current thread set at room-level. This value can also be overridden by a room-level call that is run afterwards.
Room.createComment
Creates a comment in a given thread.
- valueCommentData
The comment that has been created.
- threadIdstringRequired
The ID of the thread that the comment will be added to.
- attachmentIdsstring
The IDs of the comment’s attachments.
- bodyCommentBodyRequired
The content of the comment, see creating comment content.
Creating comment content
A comment’s body is an array of paragraphs, each containing child nodes. Here’s
an example of how to construct the following simple comment body, which can be
passed to room.createComment
.
Hello world
Second paragraph!
It’s also possible to create links and mentions.
@Jody Hekla the Liveblocks website is cool!
Room.editComment
Edits a comment, replacing its existing comment body and optionally updating its attachments. Learn more about creating comment content.
- valueCommentData
The comment that has been edited.
- threadIdstringRequired
The ID of the thread containing the comment.
- threadIdstringRequired
The ID of the comment that’s being edited.
- attachmentIdsstring
The IDs of the comment’s attachments.
- bodyCommentBodyRequired
The content of the comment, see creating comment content.
Room.deleteComment
Deletes a comment. If it is the last non-deleted comment, the thread also gets deleted.
- threadIdstringRequired
The ID of the thread containing the comment.
- threadIdstringRequired
The ID of the comment that’s being edited.
Room.addReaction
Adds a reaction from the current user on a comment.
- valueCommentUserReaction
The reaction that has been created.
- threadIdstringRequired
The ID of the thread containing the comment.
- threadIdstringRequired
The ID of the comment to add a reaction to.
- emojistringRequired
The emoji reaction to add.
Room.removeReaction
Removes a reaction from a comment.
- threadIdstringRequired
The ID of the thread containing the comment.
- threadIdstringRequired
The ID of the comment to remove a reaction from.
- emojistringRequired
The emoji reaction to remove.
Room.prepareAttachment
Creates a local attachment from a file.
- valueCommentLocalAttachment
The local attachment that has been created.
- fileFileRequired
The file to create the attachment from.
Room.uploadAttachment
Uploads a local attachment.
Optionally, an
AbortSignal
can be passed to cancel the upload.
- valueCommentAttachment
The attachment that has been uploaded.
- attachmentCommentLocalAttachmentRequired
The file to create the attachment from.
- optionsUploadAttachmentOptions
A set of options.
- signalAbortSignal
Only the inbox notifications updated or deleted after this date will be returned.
Room.getAttachmentUrl
Returns a presigned URL for an attachment by its ID.
- valuestring
A presigned URL for the attachment.
- attachmentIdstringRequired
The ID of the attachment to get the URL for.
Notifications
Client.getInboxNotifications
Returns the current user’s inbox notifications and their associated threads and subscriptions. It also returns the request date that can be used for subsequent polling.
- inboxNotificationsInboxNotificationData[]
Current user’s inbox notifications.
- threadsThreadData[]
Threads associated with the inbox notifications.
- subscriptionsSubscriptionData[]
Subscriptions associated with the inbox notifications.
- requestedAtDate
The request date to use for subsequent polling.
- roomIdstring
Only return inbox notifications for the given room. Learn more.
- kindstring
Only return inbox notifications for the kind. Learn more.
Filtering inbox notifications
You can filter inbox notifications by those that are associated with a specific
room or kind, by passing a string
to query.roomId
or query.kind
.
Client.getInboxNotificationsSince
Returns the updated and deleted inbox notifications and their associated threads
and subscriptions since the requested date. Helpful when used in combination
with Client.getInboxNotifications
to
initially fetch all notifications, then receive updates later.
- inboxNotifications
Inbox notifications that have been updated or deleted since the requested date.
- threads
Threads that have been updated or deleted since the requested date.
- requestedAtDate
The request date to use for subsequent polling.
- sinceDateRequired
Only the inbox notifications updated or deleted after this date will be returned.
Client.getUnreadInboxNotificationsCount
Gets the number of unread inbox notifications for the current user.
- valuenumber
Number of unread inbox notifications.
Client.markAllInboxNotificationsAsRead
Marks all inbox notifications as read, for the current user.
Client.markInboxNotificationAsRead
Marks an inbox notification as read, for the current user.
- inboxNotificationIdstringRequired
The ID of the inbox notification to be marked as read.
Client.deleteAllInboxNotifications
Deletes an inbox notification for the current user.
Client.deleteInboxNotification
Deletes an inbox notification for the current user.
- inboxNotificationIdstringRequired
The ID of the inbox notification to be deleted.
Room.getSubscriptionSettings
Gets the user’s subscription settings for the current room. This notates which
inboxNotifications
the current user receives in the current room.
- settings{ threads, textMentions }
Subscription settings for Liveblocks products.
- settings.threads"all" | "replies_and_mentions" | "none"
Returns the current room’s subscription settings for threads. It can return one of three values:
"all"
Receive notifications for every activity in every thread."replies_and_mentions"
Receive notifications for mentions and threads you’re participating in."none"
No notifications are received.
- settings.textMentions"mine" | "none"
Returns the current room’s subscription settings for text mentions. It can be one of two values:
"mine"
Receive notifications for mentions of you."none"
No notifications are received.
Room.updateSubscriptionSettings
Updates the user’s subscription settings for the current room. Updating this
setting will change which
inboxNotifications
the current user receives in the current room.
- settings{ threads, textMentions }
Subscription settings for Liveblocks products.
- settings.threads"all" | "replies_and_mentions" | "none"
Returns the current room’s subscription settings for threads. It can return one of three values:
"all"
Receive notifications for every activity in every thread."replies_and_mentions"
Receive notifications for mentions and threads you’re participating in."none"
No notifications are received.
- settings.textMentions"mine" | "none"
Returns the current room’s subscription settings for text mentions. It can be one of two values:
"mine"
Receive notifications for mentions of you."none"
No notifications are received.
- threads"all" | "replies_and_mentions" | "none"
Sets the current room’s subscription settings for threads. It can be one of three values:
"all"
Receive notifications for every activity in every thread."replies_and_mentions"
Receive notifications for mentions and threads you’re participating in."none"
No notifications are received.
- textMentions"mine" | "none"
Sets the current room’s subscription settings for text mentions. It can be one of two values:
"mine"
Receive notifications for mentions of you."none"
No notifications are received.
Replacing individual thread subscriptions
Subscribing will replace any existing thread subscriptions in the current room. This value can also be overridden by a room-level call that is run afterwards.
Client.getNotificationSettingsBeta
Returns the user’s notification settings in the current project, in other words which notification webhook events will be sent for the current user. Notification settings are project-based, which means that this returns the current user’s settings for every room.
A user’s initial settings are set in the dashboard, and different kinds should
be enabled there. If no kind is enabled on the current channel, null
will be
returned. For example, with the email channel:
- settingsNotificationSettings
Current user’s notification settings.
Client.updateNotificationSettingsBeta
Updates the current user’s notification settings, which affects which
notification webhook events will be
sent for the current user. Notification settings are project-based, which means
that this modifies the current user’s settings in every room. Each notification
kind
must first be enabled on your project’s notification dashboard page
before settings can be used.
- settingsNotificationSettings
Current user’s notification settings.
- settingsobjectRequired
A deep partial object containing the notification settings to update. Custom notifications can be set too.
- settings.emailNotificationChannelSettings
The email notification settings.
- settings.slackNotificationChannelSettings
The Slack notification settings.
- settings.teamsNotificationChannelSettings
The Microsoft Teams notification settings.
- settings.webPushNotificationChannelSettings
The Web Push notification settings.
Storage
Each room contains Storage, a conflict-free data store that multiple users can edit at the same time. When users make edits simultaneously, conflicts are resolved automatically, and each user will see the same state. Storage is ideal for storing permanent document state, such as shapes on a canvas, notes on a whiteboard, or cells in a spreadsheet.
Data structures
Storage provides three different conflict-free data structures, which you can use to build your application. All structures are permanent and persist when all users have left the room, unlike Presence which is temporary.
-
LiveObject
- Similar to JavaScript object. Use this for storing records with fixed key names and where the values don’t necessarily have the same types. For example, aPerson
with aname: string
and anage: number
field. If multiple clients update the same property simultaneously, the last modification received by the Liveblocks servers is the winner. -
LiveList
- An ordered collection of items synchronized across clients. Even if multiple users add/remove/move elements simultaneously, LiveList will solve the conflicts to ensure everyone sees the same collection of items. -
LiveMap
- Similar to a JavaScript Map. Use this for indexing values that all have the same structure. For example, to store an index ofPerson
values by their name. If multiple users update the same property simultaneously, the last modification received by the Liveblocks servers is the winner.
Typing Storage
To type the Storage values you receive, make sure to set your Storage
type.
The type received in the callback will match the type passed. Learn more under typing your data.
Nesting data structures
All Storage data structures can be nested, allowing you to create complex trees of conflict-free data.
Room.getStorage
Get the room’s Storage asynchronously (returns a Promise). The promise will
resolve once the Storage’s root is loaded and available. The Storage’s root is
always a LiveObject
.
- storage{ root: LiveObject<TStorage> }
The room’s Storage structures.
root
is aLiveObject
, and is the root of your Storage. Learn more about typing Storage.
LiveObject
The LiveObject
class is similar to a JavaScript object that is synchronized on
all clients. Use this for storing records with fixed key names and where the
values don’t necessarily have the same types. For example, a Person
with
name
and age
fields. To add typing, read more under
typing Storage.
Keys are strings, and values can contain other Storage structures, or JSON-serializable data. If multiple clients update the same property simultaneously, the last modification received by the Liveblocks servers is the winner.
new LiveObject
Create an empty LiveObject
Create a LiveObject
with initial data.
- LiveObjectLiveObject<L>
The newly created
LiveObject
.
- initialValueL extends LsonObjectRequired
The initial value for the
LiveObject
. Can contain JSON-serializable data and other Liveblocks conflict-free data structures.
Add a LiveObject to Storage
The Storage root is LiveObject
itself, so you can use LiveObject.set
to
add a new property to your root. If you’ve typed Storage
you’ll have type hints as you build.
delete
Delete a property from the LiveObject
- keystringRequired
The key of the property you’re deleting. If the property doesn’t exist, nothing will occur.
get
Get a property from the LiveObject
.
- value
The value of the property. Returns
undefined
if it doesn’t exist.
- keystringRequired
The key of the property you’re getting.
set
Adds or updates a property with the specified key and a value.
- keystringRequired
The key of the property you’re setting.
- valueLsonObjectRequired
The value of the property you’re setting. Can contain JSON-serializable data and other Liveblocks conflict-free data structures.
update
Adds or updates multiple properties at once. Nested changes to other Storage types will not be applied.
- valueLsonObjectRequired
The keys and values you’re updating. Can contain JSON-serializable data and other Liveblocks conflict-free data structures. Nested changes to other Storage types will not be applied.
clone
Returns a deep copy of the LiveObject
that can be inserted elsewhere in the
Storage tree.
- clonedStructureLiveObject
The cloned
LiveObject
.
toImmutable
Returns an immutable JavaScript object that is equivalent to the LiveObject
.
Nested values will also be immutable. Calling this method multiple times has no
performance penalty. It will return the same cached immutable value as long as
its (nested) contents have not changed.
- immutableStructureobject
Returns a JavaScript object in the shape of your data structure.
LiveObject
is converted to an object,LiveMap
to a map, andLiveList
to an array.
toObject
Transform the LiveObject
into a normal JavaScript object.
Please note that this method won’t recursively convert Live structures, which may be surprising:
LiveMap
The LiveMap
class is similar to a
JavaScript Map
that is synchronized on all clients. Use this for indexing values that all have
the same structure. For example, to store an index of Person
values by their
name. To add typing, read more under typing Storage.
Keys are strings, and values can contain other Storage structures, or JSON-serializable data. If multiple clients update the same property simultaneously, the last modification received by the Liveblocks servers is the winner.
new LiveMap
Create an empty LiveMap
.
Create a LiveMap
with initial data.
- LiveMapLiveMap<string, L>
The newly created
LiveMap
.
- initialValue[string, L extends LsonObject][]Required
The initial value for the
LiveMap
. An array of tuples, each containing a key and a value. The values can contain JSON-serializable data and other Liveblocks conflict-free data structures.
Add a LiveMap to Storage
The Storage root is a LiveObject
, so you can create a new LiveMap
then use
LiveObject.set
to add it to your root. If you’ve
typed Storage you’ll have type hints as you build.
delete
Removes the specified element by key. Returns true if an element existed and has been removed, or false if the element does not exist.
- deletedboolean
If the element existed and was removed.
- keystringRequired
The key of the element you’re deleting. If the element doesn’t exist, nothing will occur.
entries
Returns a new
Iterator
object that contains the [key, value]
pairs for each element.
- iteratorIterableIterator<[string, L]>
A new Iterator object for the
LiveMap
, containing the[key, value]
pairs for each element.
forEach
Executes a provided function once per each key/value pair in the Map object, in insertion order.
- callbackRequired
A callback for each entry. The callback is passed the current
value
,key
, and theLiveMap
. Return values are ignored.
get
Returns a specified element from the LiveMap
. Returns undefined
if the key
can’t be found.
- valueL | undefined
The value of the entry. Returns
undefined
if it doesn’t exist.
- keystringRequired
The key of the entry you’re getting.
has
Returns a boolean indicating whether an element with the specified key exists or not.
- existsboolean
Whether the entry exists.
- keystringRequired
The key of the entry you’re getting.
keys
Returns a new Iterator object that contains the keys for each element.
- iteratorIterableIterator<string>
A new Iterator object for the
LiveMap
, containing the keys of each entry.
set
Adds or updates an element with a specified key and a value.
- keystringRequired
The key of the entry you’re setting.
- valueLsonObjectRequired
The value of the entry you’re setting. Can contain JSON-serializable data and other Liveblocks conflict-free data structures.
size
Returns the number of elements in the LiveMap
.
- sizenumber
The number of entries in the
LiveMap
- N/A
values
Returns a new Iterator object that contains the the values for each element.
- iteratorIterableIterator<L>
A new Iterator object for the
LiveMap
, containing the values of each entry.
clone
Returns a deep copy of the LiveMap
that can be inserted elsewhere in the
Storage tree.
- clonedStructureLiveMap
The cloned
LiveMap
.
toImmutable
Returns an immutable ES6 Map that is equivalent to the LiveMap
. Nested values
will also be immutable. Calling this method multiple times has no performance
penalty. It will return the same cached immutable value as long as its (nested)
contents have not changed.
- immutableStructureobject
Returns a JavaScript object in the shape of your data structure.
LiveMap
is converted to a map,LiveObject
to an object, andLiveList
to an array.
LiveList
The LiveList
class represents an ordered collection of items that is
synchronized across clients. To add typing, read more under
typing Storage.
Items can contain other Storage structures, or JSON-serializable data.
new LiveList
Create an empty LiveList
.
Create a LiveList
with initial data.
- LiveListLiveList<L>
The newly created
LiveList
.
- initialValueArray<L extends LsonObject>Required
The initial array of values for the
LiveList
. Can contain JSON-serializable data and other Liveblocks conflict-free data structures.
clear
Removes all the elements.
delete
Deletes the element living at the specified index locally. If the index doesn't
exist, an Error
is thrown.
This operation uses ID-based semantics, not position-based. When called, it reads the item at the specified index from the local state, then sends a "delete item with ID X" instruction to the server.
If clients A and B both see a LiveList containing ["foo", "bar"]
, and client A
calls .insert("qux", 0)
, while client B simultaneously calls .delete(0)
, the
end result will always be ["qux", "bar"]
on both clients, and never
["foo", "bar"]
.
- indexnumberRequired
The index of the property you’re deleting. If the property doesn’t exist, an
Error
is thrown.
every
Tests whether all elements pass the test implemented by the provided function. Returns true if the predicate function returns a truthy value for every element. Otherwise, false.
- isEveryboolean
Whether all elements pass the test implemented by the provided function.
- callback(value: L, index: number) => unknownRequired
A function to execute for each item in the array. It should return a truthy value to indicate the element passes the test, and a falsy value otherwise. The function is passed the
value
of the item and its currentindex
.
filter
Creates an array with all elements that pass the test implemented by the provided function.
- filteredArrayL[]
An array containing each item of the
LiveList
that passed the test implemented by the provided function.
- callback(value: L, index: number) => unknownRequired
A function to execute for each item in the array. It should return a truthy value to indicate the element passes the test, and a falsy value otherwise. The function is passed the
value
of the item and its currentindex
.
find
Returns the first element that satisfies the provided testing function. If no
item passes the test, undefined
is returned.
- itemL | undefined
The item that has been found. If no item passes the test,
undefined
is returned.
- callback(value: L, index: number) => unknownRequired
A function to execute for each item in the array. It should return a truthy value to indicate the element passes the test, and a falsy value otherwise. The function is passed the
value
of the item and its currentindex
.
findIndex
Returns the index of the first element in the LiveList
that satisfies the
provided testing function. If no item passes the test, -1
is returned.
- indexnumber
The index of the item that has been found. If no item passes the test,
-1
is returned.
- callback(value: L, index: number) => unknownRequired
A function to execute for each item in the array. It should return a truthy value to indicate the element passes the test, and a falsy value otherwise. The function is passed the
value
of the item and its currentindex
.
forEach
Executes a provided function once for each element.
- callbackRequired
A callback for each item. The callback is passed the current
value
andindex
. Return values are ignored.
get
Get the element at the specified index. Returns undefined
if the index doesn’t
exist.
- itemL | undefined
The value of the item at the index. Returns
undefined
if it doesn’t exist.
- indexnumberRequired
The index of the item you’re getting.
indexOf
Returns the first index at which a given element can be found in the LiveList
.
Returns -1
if it is not present.
- indexnumber
The index of the item. Returns
-1
if it doesn’t exist.
- searchElementLRequired
The item you’re locating.
- indexnumber
The index to start the search at.
insert
Inserts one element at a specified index. Throws an Error
if the index is out
of bounds.
- valueL extends LsonObjectRequired
The value of the item you’re inserting.
- indexnumberRequired
The index to insert the item into.
lastIndexOf
Returns the last index at which a given element can be found in the LiveList
,
or -1 if it is not present. The LiveList
is searched backwards, starting at
fromIndex. Returns -1
if it is not present.
- indexnumber
The index of the item. Returns
-1
if it doesn’t exist.
- searchElementLRequired
The item you’re locating.
- indexnumber
The index at which to start searching backwards.
length
Returns the number of elements.
- lengthnumber
The number of items in the
LiveList
.
- N/A
map
Creates an array populated with the results of calling a provided function on every element.
- array
The array of each item has been transformed by the callback function.
- callbackRequired
A callback for each item. The callback is passed the current
value
andindex
. Return values are used in the returned array.
move
Moves one element at a specified index.
- indexnumberRequired
The index of the item to move.
- targetIndexnumberRequired
The index where the element should be after moving.
push
Adds one element to the end of the LiveList
.
- indexLRequired
The item to add to the end of the
LiveList
.
set
Replace one element at the specified index.
some
Tests whether at least one element in the LiveList
passes the test implemented
by the provided function.
- areSomeboolean
Whether any elements pass the test implemented by the provided function.
- callback(value: L, index: number) => unknownRequired
A function to execute for each item in the array. It should return a truthy value to indicate the element passes the test, and a falsy value otherwise. The function is passed the
value
of the item and its currentindex
.
clone
Returns a deep copy of the LiveList
that can be inserted elsewhere in the
Storage tree.
- clonedStructureLiveList
The cloned
LiveList
.
toImmutable
Returns an immutable JavaScript array that is equivalent to the LiveList
.
Nested values will also be immutable. Calling this method multiple times has no
performance penalty. It will return the same cached immutable value as long as
its (nested) contents have not changed.
- immutableStructureobject
Returns a JavaScript object in the shape of your data structure.
ListList
is converted to an array,LiveObject
to an object, andLiveMap
to a map.
toArray
Transforms the LiveList
into a normal JavaScript array.
Please note that this method won’t recursively convert Live structures, which may be surprising:
Resolvers
invalidateUsers
client.resolvers.invalidateUsers
can be used to invalidate some or all users
that were previously cached by resolveUsers
.
It can be used when updating the current user’s avatar for example, to instantly refresh the user data everywhere without having to perform a page reload.
invalidateRoomsInfo
client.resolvers.invalidateRoomsInfo
can be used to invalidate some or all
rooms that were previously cached by
resolveRoomsInfo
.
It can be used when updating a room’s name for example, to instantly refresh the room info everywhere without having to perform a page reload.
invalidateGroupsInfo
client.resolvers.invalidateGroupsInfo
can be used to invalidate some or all
groups that were previously cached by
resolveGroupsInfo
.
It can be used when updating a group’s name for example, to instantly refresh the group info everywhere without having to perform a page reload.
invalidateMentionSuggestions
client.resolvers.invalidateMentionSuggestions
can be used to invalidate all
mention suggestions that were previously cached by
resolveMentionSuggestions
.
It can be used when updating a room’s list of users for example, to prevent creating out-of-date mentions without having to perform a page reload.
Utilities
getMentionsFromCommentBody
Returns an array of mentions from a CommentBody
(found under comment.body
).
An optional second argument can be used to filter the returned mentions. By default, if it’s not provided, all mentions are returned, including future mention kinds (e.g. group mentions in the future).
Here’s an example with a custom CommentBody
.
stringifyCommentBody
Used to convert a CommentBody
(found under comment.body
) into either a plain
string, Markdown, HTML, or a custom format.
A number of options are available.
Formatting examples
Here are a number of different formatting examples derived from the same
CommentBody
.
TypeScript
Typing your data
It’s possible to have automatic types flow through your application by defining
a global Liveblocks
interface. We recommend doing this in a
liveblocks.config.ts
file in the root of your app, so it’s easy to keep track
of your types. Each type (Presence
, Storage
, etc.), is optional, but it’s
recommended to make use of them.
Here are some example values that might be used.
Typing with client.enter
Before Liveblocks 2.0, it was recommended to type your data by passing
Presence
, Storage
, UserMeta
, and RoomEvents
types to
client.enterRoom
. This is no longer
the recommended method for setting up Liveblocks, but it
can still be helpful, for example you can use client.enter
multiple times to
create different room types, each with their own correctly typed hooks.
You can also pass types to
client.getRoom
.
ToolDefinition
Type definition for AI tools that can be executed by the AI. This type represents the structure of a tool that can be registered and used in AI interactions.
- descriptionstring
A clear description of what the tool does. Used by AI to understand when to call this tool.
- parametersJSONSchema7
JSON Schema defining the tool’s input parameters. The AI will validate arguments against this schema.
- executefunction
Async function that performs the tool’s action. Receives validated arguments and execution context, returns structured data.
- renderfunction
React component function that renders the tool’s UI during different execution stages.
AiKnowledgeSource
Type definition for knowledge sources that provide contextual information to AI. Knowledge sources help the AI understand your application’s current state and make more informed responses.
- descriptionstring
A clear description of what this knowledge represents (e.g., "Current user’s profile", "Application settings").
- valuestring | object | array | number | boolean | null
The knowledge content. Can be any JSON-compatible format that provides context to the AI.
Knowledge sources can be registered using
RegisterAiKnowledge
or passed directly to AiChat
via the knowledge
prop.
User
User
is a type that’s returned by room.getSelf
, room.getOthers
,
and other functions. Some of its values are set when
typing your room, here are some example values:
- connectionIdnumber
The connection ID of the User. It is unique and increments with every new connection.
- idUserMeta["id"]
The ID of the User that has been set in the authentication endpoint. Useful to get additional information about the connected user.
- infoUserMeta["info"]
Additional user information that has been set in the authentication endpoint.
- presenceTPresence
The user’s Presence data.
- canWriteboolean
True if the user can mutate the Room’s Storage and/or YDoc, false if they can only read but not mutate it.
- canCommentboolean
The ID of the User that has been set in the authentication endpoint. Useful to get additional information about the connected user.
Deprecated
Client.enterDeprecated
Enters a room and returns its local Room
instance.
Client.leaveDeprecated
Leaves a room.
Room.getNotificationSettingsDeprecated
Gets the user’s subscription settings for the current room. This notates which
inboxNotifications
the current user receives in the current room.
Room.updateNotificationSettingsDeprecated
Updates the user’s subscription settings for the current room. Updating this
setting will change which
inboxNotifications
the current user receives in the current room.