Collaboration
Real-time presence and multiplayer features through Liveblocks.
@repo/collaboration provides real-time collaborative features through
Liveblocks. apps/app uses it for an avatar stack and live cursors.
LIVEBLOCKS_SECRET environment variable.How it works
Liveblocks organises collaboration into rooms. Both halves of the setup — user authentication and the providers — are already wired in this package.
Two provider props are wired with it: resolveUsers and resolveMentionSuggestions, which resolve users and mention suggestions against the Clerk directory.
Usage
Liveblocks provides a number of hooks making it easy to add real-time presence and document storage to your app. For example, useOthers returns which users are currently connected, helpful for building avatars stacks and multiplayer cursors.
import { useOthers, useSelf } from "@liveblocks/react/suspense";
export function ToolbarAvatars() {
const others = useOthers();
const me = useSelf();
return (
<div>
{/* Your avatar */}
<Avatar src={me.info.avatar} name={me.info.name} />
{/* Everyone else's avatars */}
{others.map(({ connectionId, info }) => (
<Avatar key={connectionId} src={info.avatar} name={info.name} />
)}
</div>
);
}Multiplayer documents
You can take your collaborative app a step further, and set up multiplayer document state with useStorage and useMutation. This is ideal for creating custom experiences, such as a a multiplayer drawing panel, spreadsheet, or just a simple shared input and that anyone can edit.
import { useStorage, useMutation } from "@liveblocks/react/suspense";
function CollaborativeInput() {
// Get the input's value
const inputValue = useStorage((root) => root.inputValue);
// Set the input's value
const setValue = useMutation(({ storage }, newValue) => {
storage.set("inputValue", newValue);
}, []);
return <input value={inputValue} onChange={(e) => setValue(e.target.value)} />;
}Commenting
Liveblocks also provides ready-made customizable components for adding collaboration, such as Thread and Composer.
import { useThreads } from "@liveblocks/react/suspense";
import { Thread, Composer } from "@liveblocks/react-ui";
function Comments() {
// Get each thread of comments and render them
const { threads } = useThreads();
return (
<div>
{threads.map((thread) => (
<Thread key={thread.id} thread={thread} />
))}
<Composer />
</div>
);
}Collaborative editing
To add a rich-text editor with full collaborative editing and floating comments, you can set up a Tiptap or Lexical editor in a few lines of code.
import { useLiveblocksExtension, FloatingComposer, FloatingThreads } from "@liveblocks/react-tiptap";
import { useThreads, useEditor, EditorContent } from "@tiptap/react";
import StarterKit from "@tiptap/starter-kit";
export function Editor() {
const { threads } = useThreads();
const liveblocks = useLiveblocksExtension();
// Set up your multiplayer text editor
const editor = useEditor({
extensions: [
liveblocks,
StarterKit.configure({ history: false }),
],
immediatelyRender: false,
});
return (
<div>
<EditorContent editor={editor} />
<FloatingThreads
editor={editor}
threads={threads}
/>
<FloatingComposer editor={editor} />
</div>
);
}Notifications
Liveblocks also provides notification components, meaning you can send in-app notifications to users that are tagged in comments, are mentioned in the text editor, or for any custom purpose.
import { useInboxNotifications } from "@liveblocks/react/suspense";
import {
InboxNotification,
InboxNotificationList,
} from "@liveblocks/react-ui";
export function CollaborativeApp() {
// Get each notification for the current user
const { inboxNotifications } = useInboxNotifications();
return (
<InboxNotificationList>
{inboxNotifications.map((inboxNotification) => (
<InboxNotification
key={inboxNotification.id}
inboxNotification={inboxNotification}
/>
))}
</InboxNotificationList>
);
}Infrastructure
Liveblocks not only provides these features, but it also has:
- Browser DevTools to help you build your app.
- REST APIs for sever-side changes.
- Node.js SDK for using the REST APIs with TypeScript.
- Webhooks for triggering user-driven events.
- Dashboard to help with bug spotting and analytics.
Learn more by checking out the Liveblocks documentation, examples, and interactive tutorial.