Liveblocks
Real-time collaboration infrastructure for building Figma/Notion-like features. Provides cursors, presence, comments, notifications, and document locking out of the box — no WebSocket server needed.
Why Liveblocks?
Building collaborative editing features (like Google Docs)
Need multiplayer cursors and presence indicators
Adding comments/annotations to your app without building infra
Signal Breakdown
What drives the Trust Score
Download Trend
Last 12 months
Tradeoffs & Caveats
Know before you commitGeneral-purpose pub/sub — Ably or Pusher are better fits
No React/TypeScript stack — Liveblocks is heavily React-centric
Need self-hosting — Liveblocks is cloud-only
Pricing
Free tier & paid plans
50 MAU · unlimited rooms
From $99/mo (Starter)
MAU-based pricing
Alternative Tools
Other options worth considering
The most widely used real-time bidirectional event-based communication library. Works across browsers and Node.js with automatic fallbacks and built-in reconnection.
Often Used Together
Complementary tools that pair well with Liveblocks
Learning Resources
Docs, videos, tutorials, and courses
Get Started
Repository and installation options
View on GitHub
github.com/liveblocks/liveblocks
npm install @liveblocks/client @liveblocks/reactQuick Start
Copy and adapt to get going fast
import { createClient } from '@liveblocks/client';
import { createRoomContext } from '@liveblocks/react';
type Presence = { cursor: { x: number; y: number } | null };
type Storage = {};
const client = createClient({ publicApiKey: process.env.NEXT_PUBLIC_LIVEBLOCKS_KEY! });
export const { RoomProvider, useOthers, useUpdateMyPresence } =
createRoomContext<Presence, Storage>(client);Code Examples
Common usage patterns
Live cursors
Show real-time cursors of all connected users
'use client';
import { useOthers, useUpdateMyPresence } from '../liveblocks.config';
export function LiveCursors() {
const others = useOthers();
const updatePresence = useUpdateMyPresence();
return (
<div
className="relative w-full h-full"
onPointerMove={(e) =>
updatePresence({ cursor: { x: Math.round(e.clientX), y: Math.round(e.clientY) } })
}
onPointerLeave={() => updatePresence({ cursor: null })}
>
{others.map(({ connectionId, presence }) =>
presence.cursor ? (
<div
key={connectionId}
className="absolute w-4 h-4 bg-blue-500 rounded-full pointer-events-none"
style={{ left: presence.cursor.x, top: presence.cursor.y }}
/>
) : null
)}
</div>
);
}Thread comments
Add threaded comments to any element
import { useCreateThread, useThreads } from '../liveblocks.config';
import { Composer, Thread } from '@liveblocks/react-comments';
export function Comments() {
const { threads } = useThreads();
const createThread = useCreateThread();
return (
<div>
{threads.map((thread) => (
<Thread key={thread.id} thread={thread} />
))}
<Composer
onComposerSubmit={({ body }, e) => {
e.preventDefault();
createThread({ body, metadata: {} });
}}
/>
</div>
);
}Community Notes
Real experiences from developers who've used this tool