Presence
Presence is temporary state associated with each connected user in a room, updating in realtime and disappearing when the connection ends. Use Presence for creating live avatars, realtime cursors, multiplayer selections, typing indicators, and other temporary UI elements that do not belong in the persisted document. You can also set Presence on the server, enabling AI agent Presence in your app.
Ready-made components
If you’d like to get started quickly, Liveblocks provides basic ready-made
components for Presence,
Cursors and
AvatarStack, which
correspondingly display realtime cursors and avatars.
Follow the Presence quickstart guide to set them up.
Custom Presence
Using Liveblocks React hooks, you can build any sort of realtime UI Presence into your app. Presence is represented by a JSON object, and is updated in realtime for every connected user. Before you get started, decide on the shape of your Presence object, and set it in your config file.
For example, live cursors will use x and y coordinates, whereas a typing
indicator will use a boolean value. Set this in your config file.
Next, set an initial value for your Presence in
RoomProvider. In this
snippet, null represents a cursor that is offscreen.
Set up user info
When using Presence, it's often useful to pass in user info from your authentication system, such as a name, avatar, and color, to be displayed in the UI. This is helpful if you’re rendering UI such as a user avatar or name tag, static information that won’t update in realtime.
To do this, first, set your types in liveblocks.config.ts. For example, if
each user has the properties we just described.
Next, when authenticating Liveblocks, pass
corresponding user info from your auth system to userInfo inside your
authentication endpoint. Any string, number, or boolean property can be passed
in.
Setting user Presence
useUpdateMyPresence
allows you to update the current user’s Presence. Use this, for example, to set
a user’s cursor position on the page, or set a typing indicator.
Using others' Presence
useOthers returns a list of
every connected users in the room. For example, you can render each user’s
cursor using their presence.cursor values, passing in their
user info from before to show their name and color.
Avatar stack
After adding user info, you can render a live avatar stack
wuth useOthers and your
info.avatar property.
Typing indicator
To create a typing indicator, use
useUpdateMyPresence
to set typing to true on input, then clear it with a timeout after the user
stops typing.
Selection indicator
To create a selection indicator, use
useUpdateMyPresence
to set selection on an item, then add an outline when the item is selected. In
this example, multiple textareas are rendered, and when one is selected by a
user, an outline appears around it.
Server-side Presence
As well as on the client, you can set Presence on the server, especially helful
for enabling AI agent Presence in your app. The
Liveblocks.setPresence
method is used for this, and after it’s called,
useOthers will return the
agent in the list of connected users. data and userInfo correspond to
Presence and UserInfo in your types.
Presence expires after the time-to-live (TTL) period, in seconds, and is removed
from the list of connected users. To remove agent Presence, call it with
ttl: 2, the minimum value, and it will be removed shortly after.
Example usage
One way to use agent Presence is to set it before running an AI workflow, then remove it after the workflow is complete. Here’s an example that modifies a Sync document, displaying an AI avatar as it does the work. Avatars don’t need any Presence data, so we can set it to an empty object.
Set Presence before and after running the AI workflow, setting ttl to the
minimum value at the end.
In the front end, agent-123 will appear in the list of connected users, and
the AI avatar will be displayed in the UI.
Display all agents under a single avatar
If you’d prefer all AI agents in the room to be displayed as single avatar,
instead of showing a single avatar for each, modify your stack to account for
this. This snippet assumes each agent’s user ID begins with agent-.