Best Boilerplates for Real-Time Collaboration Apps 2026
TL;DR
- Liveblocks is the best managed infrastructure for collaboration — presence, shared state, Yjs-based co-editing, and comments without running WebSocket servers
- PartyKit is the right choice for stateful edge logic: multiplayer games, live polls, canvas collaboration, and anything that needs a persistent server per room
- Yjs + Hocuspocus self-hosted is the cost-effective path at scale once Liveblocks pricing becomes a real line item, with full control over persistence and authentication
- Ably (pub/sub) handles the simpler end of the spectrum: live feeds, notifications, and cursor presence without CRDT complexity
- Never implement CRDTs from scratch — the correctness requirements are subtle and the existing libraries (Yjs, Automerge) have years of battle-testing
What Real-Time Collaboration Actually Requires
Real-time collaboration is one of the hardest SaaS features to build correctly. Google Docs-style co-editing requires CRDTs for conflict resolution, Figma-style presence requires cursor sync and member awareness, and both require infrastructure that stays alive while users are connected.
But "real-time collaboration" covers a spectrum of complexity, and misidentifying where your product falls on that spectrum leads to over-building or under-building. The four tiers:
Presence-only is the simplest form. Show who else is on the page: cursor positions, "Jane is viewing this" indicators, selection highlights. There's no conflict resolution because presence data is ephemeral — last-write-wins for cursor position is always acceptable. If Jane moves her cursor and the update is 50ms late, nobody cares. Implementation time with Liveblocks or Pusher presence channels: 1-2 days. The infrastructure is straightforward: a WebSocket channel per room, presence enter/leave events, and heartbeat updates for cursor position.
Optimistic updates with locks is the medium-complexity tier. One user edits at a time. When a user starts editing a field, a lock is acquired; other users see the field as "locked by Jane" and cannot edit it. This is how many SaaS tools handle "collaboration" — Figma uses this model for component editing, many project management tools use it for task descriptions. It's technically much simpler than full CRDTs because you never have two conflicting edits to merge. Implementation time: 3-5 days. The edge cases are lock timeouts (what happens if Jane locks a field and closes her browser?), lock persistence (does a lock survive a server restart?), and UX for contested locks (do you show who holds the lock and when it expires?).
Full concurrent editing is the hardest tier. Multiple users can edit the same text simultaneously. Neither user is blocked; both edits are merged without data loss. This is what Google Docs, Notion, and Figma's text editing does. The underlying mechanism — CRDTs (Yjs, Automerge) or Operational Transformation (ShareDB) — is complex distributed systems territory. Implementation time from scratch: months. Using a library: weeks for full integration. This is the tier where the choice between Liveblocks, PartyKit, and self-hosted Yjs matters significantly.
Canvas collaboration (the Figma tier) adds spatial awareness to full concurrent editing. Multiple users can move objects on an infinite canvas, resize shapes, draw, and annotate. The state model is more complex than text because objects have position, size, z-index, and parent-child relationships. Yjs's Map and Array types handle this, but the rendering layer (keeping a canvas in sync with a shared Yjs document) is the engineering work.
Quick Comparison
| Tool | Price | CRDT | Presence | Storage | Best For |
|---|---|---|---|---|---|
| Liveblocks | Free-$99/mo | ✅ | ✅ | ✅ Yjs | Figma-style collaboration |
| PartyKit | Free-$X/mo | ✅ | ✅ | Manual | Durable server logic |
| Yjs + Hocuspocus | Free | ✅ | ✅ | Manual | Self-hosted collaborative |
| Pusher Channels | Free-$49/mo | ❌ | Manual | Manual | Simple real-time events |
Liveblocks — Best Collaboration Infrastructure
Price: Free (up to 50 connections) / $99+/month | Creator: Liveblocks team
Liveblocks provides the real-time infrastructure for collaborative experiences: cursor presence, shared state (Storage), collaborative text editing (Yjs), and comments.
// Real-time collaborative text editor with Liveblocks + TipTap
import { RoomProvider, useOthers } from '@liveblocks/react';
import { useLiveblocksExtension } from '@liveblocks/react-tiptap';
import { useEditor, EditorContent } from '@tiptap/react';
function CollaborativeEditor({ roomId }: { roomId: string }) {
return (
<RoomProvider id={roomId} initialPresence={{ cursor: null }}>
<Editor />
</RoomProvider>
);
}
function Editor() {
const liveblocks = useLiveblocksExtension();
const others = useOthers();
const editor = useEditor({
extensions: [
liveblocks, // Handles all collaboration sync
// Other TipTap extensions...
],
});
return (
<div>
{/* Show other users' cursors */}
{others.map(user => (
<Cursor key={user.connectionId} presence={user.presence} />
))}
<EditorContent editor={editor} />
</div>
);
}
What Liveblocks handles for you: WebSocket connections, CRDT sync, presence management, offline recovery, conflict resolution, storage persistence. You write the UI; Liveblocks handles the distributed systems complexity.
Liveblocks pricing in depth: The free tier covers 50 simultaneous connections and 1 MAU (monthly active user), which is fine for development but nothing else. The $99/month Starter tier covers up to 100 MAU with 50 simultaneous connections. For a product with 1,000 active users who use collaboration features, you're looking at the Pro tier ($199/month or custom pricing based on MAU). At 10,000 MAU, Liveblocks becomes a significant infrastructure cost — budget $500-2,000/month depending on usage patterns.
Storage vs Yjs in Liveblocks: Liveblocks offers two storage primitives. Liveblocks Storage is a key-value store optimized for structured data (think: a collaborative whiteboard where each shape is an object with position and properties). Liveblocks Yjs is for document-style text editing, wrapping Yjs's CRDT data structures in Liveblocks's sync infrastructure. For most use cases, Yjs is the right choice for text editing and Storage for everything else. The practical distinction: if your users are co-editing a text document, use Yjs. If they're collaborating on structured data (shapes, nodes, tasks), use Storage.
Liveblocks Comments is a significant included feature. Building a threaded comment system anchored to specific regions of content (like Figma's comment pins or Google Docs's margin comments) would take weeks independently. Liveblocks Comments provides this as an SDK: useCreateThread, useThreads, useEditComment hooks that handle the data model, real-time sync, and notification infrastructure. The cost to build this yourself — anchored comments, threading, reactions, read/unread state, resolution — is 2-4 weeks. Getting it for free as part of Liveblocks's SDK is one of the strongest arguments for the managed approach.
Presence: Who's Here?
// Show real-time presence (who's viewing the document)
import { useOthers, useSelf, useUpdateMyPresence } from '@liveblocks/react';
function PresenceAvatars() {
const currentUser = useSelf();
const others = useOthers();
const updatePresence = useUpdateMyPresence();
// Track cursor position
const onPointerMove = useCallback((e: PointerEvent) => {
updatePresence({ cursor: { x: e.clientX, y: e.clientY } });
}, [updatePresence]);
return (
<div onPointerMove={onPointerMove}>
{others.map(user => user.presence.cursor && (
<Cursor key={user.id} x={user.presence.cursor.x} y={user.presence.cursor.y} />
))}
</div>
);
}
Beyond cursor tracking, presence data enables richer collaborative UX. Distinguish active editors (currently typing or selecting) from passive viewers — show editors prominently with live cursor positions, show viewers as a quiet "3 others viewing" count. When a user has a text range selected, show it highlighted in their color to all other users. This selection awareness prevents edit conflicts by making intent visible before the edit happens, and it's a one-liner with Liveblocks's presence API.
CRDTs: The Theory Behind Conflict-Free Editing
When two users edit the same text simultaneously, CRDTs ensure both edits are preserved correctly:
// Yjs — CRDT-based collaborative editing
import * as Y from 'yjs';
import { WebsocketProvider } from 'y-websocket';
const doc = new Y.Doc();
const provider = new WebsocketProvider('wss://your-server.com', 'room-name', doc);
// Y.Text handles concurrent edits with CRDTs
const text = doc.getText('content');
text.insert(0, 'Hello'); // User A inserts at position 0
text.insert(0, 'World '); // User B inserts at position 0 simultaneously
// Result (CRDT resolves deterministically): "World Hello" or "Hello World"
// No data loss, no conflicts
CRDTs work by giving every operation a unique, globally sortable identifier. When two operations conflict (both insert at position 0), the CRDT resolves the conflict deterministically using those identifiers — both users see the same result regardless of which operation arrived first at each client.
Understanding this is important for product design: CRDT-based editing preserves all input, but the result may not be what either user intended. A "last write wins" approach where one user's edit overwrites the other's is sometimes the better UX for certain field types (status fields, single-select dropdowns) even though CRDTs are more technically "correct."
PartyKit — Durable Edge Servers
Price: Free tier / pay-as-you-go above free limits | Creator: Sunil Pai + Cloudflare team
PartyKit runs stateful servers on Cloudflare's edge network using Durable Objects — Cloudflare Workers that maintain a persistent state and can hold open WebSocket connections. The key difference from serverless WebSocket approaches: a PartyKit "party" (server) lives as long as it has connected clients, automatically hibernates when empty, and wakes up when new clients connect. No server management, no connection pooling, no horizontal scaling headaches.
The programming model is a class with lifecycle methods: onConnect, onMessage, onClose. Each party instance handles its own connections and state. Because Cloudflare Durable Objects run at the edge, latency is low regardless of where your users are located — Cloudflare routes connections to the nearest edge location.
PartyKit's sweet spot is use cases where each "room" needs its own persistent server: multiplayer games (each game session is a party), live polls (each poll is a party), collaborative canvas (each document is a party), and live Q&A sessions (each event is a party). The hibernation feature is crucial for cost efficiency — a party that goes idle for hours or days is not consuming resources.
Compared to Liveblocks, PartyKit is lower-level: you write more code (the server logic, the conflict resolution strategy, the storage persistence), but you have full control over what happens in each room. PartyKit doesn't include built-in CRDT infrastructure — you'd integrate Yjs yourself on the PartyKit server. For products where the room logic is custom (not just collaborative text editing), PartyKit's flexibility is the right tradeoff.
Yjs + Hocuspocus: Self-Hosted Yjs Server
For teams that need self-hosted collaborative editing (data sovereignty, compliance, cost at scale):
npm install @hocuspocus/server
// server.ts
import { Server } from '@hocuspocus/server';
import { Database } from '@hocuspocus/extension-database';
import { Logger } from '@hocuspocus/extension-logger';
const server = Server.configure({
port: 1234,
extensions: [
new Logger(),
new Database({
// Persist document state to PostgreSQL
fetch: async ({ documentName }) => {
const doc = await prisma.document.findUnique({
where: { id: documentName },
});
return doc?.content ?? null;
},
store: async ({ documentName, state }) => {
await prisma.document.upsert({
where: { id: documentName },
create: { id: documentName, content: state },
update: { content: state },
});
},
}),
],
async onAuthenticate({ token }) {
// Verify the user's auth token
const user = await verifyToken(token);
if (!user) throw new Error('Unauthorized');
return user;
},
});
server.listen();
Hocuspocus gives you full control over persistence, authentication, and scaling. The tradeoff versus Liveblocks: you manage the WebSocket server infrastructure (scaling, uptime, connection limits).
Redis for persistence: The Hocuspocus database extension above persists Yjs document state to PostgreSQL on every save, but in-memory state between saves is held in the Hocuspocus server process. For production deployments with multiple Hocuspocus instances (horizontal scaling for >1,000 concurrent users), add the Redis extension: @hocuspocus/extension-redis. This allows multiple Hocuspocus servers to share state — any server can handle any client, and document state is synchronized via Redis pub/sub.
Cost comparison vs Liveblocks: Running Hocuspocus self-hosted at 1,000 MAU costs roughly $20-40/month (a $12/month VPS for the Hocuspocus server plus Redis at $15/month on Railway or equivalent). Liveblocks at 1,000 MAU with the Pro plan costs $199/month. The self-hosted savings are real, but come with operational overhead — you manage availability, scaling, and Redis. At 100 MAU or fewer, Liveblocks's free or $99 tier is clearly the right choice. At 5,000+ MAU, self-hosted Hocuspocus's economics become compelling.
Ably — Pub/Sub Alternative
Price: Free (6 million messages/month) / $29+/month | Creator: Ably
Ably is a managed pub/sub platform — not a CRDT system. The distinction matters enormously for choosing the right tool. Ably handles message delivery: you publish an event on a channel, subscribers on that channel receive it. There's no built-in conflict resolution, no document state persistence, no CRDT semantics. Last message wins.
This makes Ably the right tool for a specific tier of real-time features: live feeds, notification delivery, cursor presence (where last-write-wins is fine), and collaborative features where conflicts are prevented by design (one user edits at a time, with locks).
Ably vs Pusher: Ably is generally considered the more enterprise-grade option with better guaranteed delivery semantics, message history, and edge network reach. Pusher is simpler to get started with and has better documentation for small-scale use cases. For presence-only features at small-to-medium scale, Pusher is fine. For high-volume pub/sub with delivery guarantees, Ably is the stronger choice.
When Ably (or Pusher) is the wrong choice: any use case where two users can write to the same state simultaneously and both writes should be preserved. Adding a comment, editing shared text, drawing on a canvas — these require CRDT semantics that pub/sub systems don't provide.
Canvas Collaboration
Canvas collaboration (multiplayer drawing, whiteboard, diagram tools) is a specific pattern with additional complexity beyond text collaboration. The state model is spatial: objects have positions, sizes, rotation, and z-index. Multiple users can move and resize objects simultaneously.
Excalidraw's architecture (open source multiplayer whiteboard) is the canonical reference implementation. Excalidraw uses Yjs to sync the canvas element array — each shape is a Yjs Map with its properties. Position updates from cursor drags are high-frequency events that go through Yjs's awareness protocol (ephemeral, not persisted to the Yjs document) rather than the document itself, keeping the persistent document state to intentional shape changes. The rendering layer reads the Yjs document state and re-renders the canvas on each update.
tldraw is a mature React canvas component library that handles the rendering and state management for canvas collaboration. tldraw's store is observable and can be synchronized via any state sync mechanism — Yjs, Liveblocks Storage, or a custom WebSocket protocol. If you're building a whiteboard or diagram product, tldraw as a rendering library plus Liveblocks or Yjs for sync is 2-3 weeks of work for a polished multiplayer canvas, versus months building from scratch.
The hardest part of canvas collaboration is handling concurrent moves of the same object. If two users drag the same shape simultaneously, the CRDT-resolved result is deterministic but might not be either user's intention. For canvas tools, a distributed lock approach (only one user can drag an object at a time; others see it as locked during a drag) often produces better UX than CRDT merging of position updates.
Offline-First Architecture
Offline-first design is natural companion to real-time collaboration: if your app works without a network connection and syncs when reconnected, it also handles the flaky network connections and brief disconnections that are common in real-world collaborative use.
The standard stack: Yjs for the document state (Yjs documents are append-only CRDT logs — you can merge any two Yjs documents created from the same base, regardless of when they were updated), IndexedDB via the y-indexeddb persistence provider for local storage of the Yjs document state, and a WebSocket or HTTP sync mechanism that reconciles local and remote state on reconnection.
The IndexedDB persistence provider stores the entire Yjs document state locally. When the user opens the app offline, they're working with their locally cached document. When connectivity is restored, the provider syncs local changes to the remote Hocuspocus or Liveblocks server. Because Yjs uses CRDTs, changes made offline and changes made by other users during the offline period are merged correctly without manual conflict resolution.
Conflict resolution strategies for non-CRDT data (database records, structured forms) in offline-first apps are more complex. The options: last-write-wins (simplest, loses the offline user's changes), server-wins (ignores offline changes), client-wins (may override concurrent changes by others), and three-way merge (compares client, server, and common ancestor — the git model). Most offline-first apps use last-write-wins with a timestamp for simplicity, and reserve three-way merge for high-value data where losing changes is unacceptable.
Real-Time Infrastructure Costs
WebSocket infrastructure is expensive at scale in a way that HTTP is not. An HTTP request takes milliseconds and releases its server resources immediately. A WebSocket connection holds open a file descriptor for as long as the user is connected — potentially hours. At 10,000 concurrent users, a Node.js WebSocket server is holding 10,000 open file descriptors and paying memory and CPU for each connection.
Managed vs self-hosted cost comparison at scale:
- 100 concurrent connections: Liveblocks free tier, or self-hosted at $0 (any server handles this trivially)
- 1,000 concurrent connections: Liveblocks $99-199/month, or self-hosted Hocuspocus at $20-40/month (single server + Redis)
- 10,000 concurrent connections: Liveblocks custom pricing ($500+/month), or self-hosted cluster at $100-200/month (3-4 servers + Redis + load balancer)
- 100,000 concurrent connections: Liveblocks enterprise, or self-hosted at $500-1,000/month with significant engineering investment
The self-hosted economics become compelling at 5,000+ connections, but the operational burden (availability, scaling, incident response) is real. Many teams start on Liveblocks, validate the product, and migrate to self-hosted Hocuspocus once they've proven the business case and can justify the engineering investment.
When NOT to Build Real-Time Collaboration
Real-time collaboration adds significant complexity:
- Infrastructure cost (WebSocket servers, always-on connections)
- Debugging complexity (race conditions are hard to reproduce)
- State management (optimistic updates, conflict resolution)
- Testing (multi-client scenarios require special tooling)
Build real-time collaboration only when:
- Multiple users editing the same document simultaneously is core to your product value
- Your product won't succeed without it (most products don't need it)
Use async collaboration instead:
- Async collaboration (leave comments, @mentions) satisfies 80% of "collaboration" use cases
- Optimistic updates with server-side validation covers most CRUD workflows
- No CRDT complexity required
The right question is: "do my users need to see each other's changes in under 200ms?" If yes, you need real-time. If "within a few seconds on refresh" is acceptable, polling or server actions are simpler.
Methodology
Collaboration infrastructure comparison based on direct evaluation of Liveblocks, PartyKit, and Yjs ecosystem as of Q1 2026. CRDT theory based on the Yjs documentation and Martin Kleppmann's research on CRDTs. Pricing from official sources as of Q1 2026.
For open source SaaS foundations to build collaborative tools on, see Best Open Source SaaS Boilerplates 2026. If your collaboration product includes a community component, see Best Boilerplates for Community Apps 2026. Browse all boilerplates in the StarterPick directory.
See also: best SaaS boilerplates 2026 for the full-stack starters most commonly used as the foundation for collaborative products.
Check out this boilerplate
View Liveblockson StarterPick →