DEV Community

Cover image for Real-Time Collaborative Editing in a React Block Editor Using Yjs
Lucy Muturi for Syncfusion, Inc.

Posted on • Originally published at syncfusion.com on

Real-Time Collaborative Editing in a React Block Editor Using Yjs

TL;DR: Learn how to add real-time collaboration to a React Block Editor using Yjs and WebSockets. This guide walks through building a shared editing experience with live document synchronization, user presence, and remote cursors without implementing custom conflict-resolution logic. You’ll also explore provider selection, production considerations, and best practices for creating reliable multi-user editing experiences.

Most developers think collaborative editing is simple, until they try building it.

Allowing multiple users to edit the same document in real-time involves much more than syncing text. You need to:

  • Handle concurrent changes,
  • Keep document state consistent,
  • Show active users,
  • Display remote cursors, and
  • Recover from connection interruptions without losing data.

That’s why features that feel effortless in tools like Google Docs are surprisingly difficult to implement.

If you’re building documentation portals, product specifications, incident reports, contracts, or knowledge bases, real-time collaboration is often a user expectation today.

The good news is that you don’t have to solve these challenges from scratch. The Syncfusion® React Block Editor provides a collaboration module designed to integrate with Yjs, a CRDT-based framework that manages synchronization and conflict resolution automatically, letting you focus on the editing experience rather than the underlying complexity.

In this guide, we’ll build a real-time collaborative editor using React, TypeScript, Yjs, and WebSockets. We’ll cover document synchronization, user presence, remote cursors, choosing the right Yjs provider, and key considerations for production deployments.

When does real-time collaboration make sense?

Real-time collaboration is ideal when multiple users need to edit the same document simultaneously while seeing live updates, presence indicators, and remote cursors.

Common use cases include:

  • Product specifications and PRDs,
  • Legal drafts and contract reviews,
  • Incident reports and postmortems,
  • Launch plans and project documentation,
  • OKR and team planning documents.

However, this approach may not be the best fit for:

  • Large wiki-style document networks,
  • Fully offline mobile applications, and
  • Scenarios that require direct device-to-device CRDT synchronization without a server.

Understanding what “real-time collaboration” actually means

Before diving into the implementation, it’s useful to understand a few concepts that power the collaborative experience.

CRDTs: The foundation of conflict-free editing

At the heart of Yjs is a Conflict-Free Replicated Data Type (CRDT). A CRDT allows multiple users to edit shared content simultaneously while ensuring every participant eventually sees the same document state.

The practical benefit is simple: two users can make changes at the same time without accidentally overwriting one another’s work.

Awareness: Knowing who’s doing what

Collaboration isn’t just about synchronizing content. Users also need context about other participants.

Yjs uses an awareness layer to share temporary information such as:

  • Cursor positions,
  • Text selections,
  • User names, and
  • Avatar information.

Because awareness data is temporary, it disappears when a user disconnects and doesn’t become part of the document itself.

Shared document state

Actual document content lives inside a shared Y.Doc file. Unlike awareness data, modifications stored in the document persist and can be synchronized across reconnects and future editing sessions.

Together, the shared document and awareness layer create the experience users expect from modern collaborative applications.

Why real-time collaboration matters

Modern editors need to support more than rich text. Users expect teams to create, review, and update content together without worrying about version conflicts or overwritten changes.

The Syncfusion React Block Editor treats content as independent blocks, such as paragraphs, headings, tables, callouts, and code snippets, making it easier to edit and organize content while maintaining a smooth writing experience. When combined with Yjs, both content changes and document structure stay synchronized across connected users.

This enables two key capabilities:

  • Edit simultaneously without conflicts: Yjs automatically resolves concurrent changes, so that multiple users can work in the same document at the same time.
  • See collaboration in real-time: Remote cursors, selections, and user presence indicators make it easy to understand who is editing and where changes are happening.

What you get out of the box

The collaboration module builds on Yjs and works alongside existing Block Editor features such as slash commands, rich text formatting, drag-and-drop, mentions, labels, paste cleanup, and accessibility support.

Key capabilities include:

  • Real-time multi-user editing with automatic conflict resolution.
  • Live user presence, selections, and remote cursors.
  • Per-user undo and redo, allowing users to revert only their own changes.
  • Synchronized rich text formatting, including headings, lists, links, colors, alignment, and inline styles.
  • Mention and label synchronization with metadata preserved across all users.
  • Support for multiple Yjs providers, including y-websocket, y-webrtc, Hocuspocus, Liveblocks, PartyKit, and more.

Whether someone is updating text, reordering sections, or adding a new callout block, every connected user sees changes reflected in real-time.

How real-time collaboration works

Behind the scenes, collaboration relies on three components: a shared Yjs document, a provider that synchronizes connected clients, and the Block Editor that renders and updates content.

Yjs collaboration


The process is straightforward:

  1. Each client initializes a Y.Doc file and creates a shared Y.XmlFragment called blockeditor.
  2. A YjsAdapter provides the editor with access to the Yjs runtime and the shared fragment.
  3. A Yjs provider connects all clients to the same collaboration room.
  4. The React Block Editor renders content from the shared fragment and writes local changes back to it. Yjs then automatically synchronizes those changes across all connected clients.
  5. When awareness is enabled, cursor positions, selections, and user information are exchanged through a separate channel.

As a result, multiple users can edit the same document simultaneously while keeping content, structure, and collaboration state synchronized.

Choosing the right Yjs provider

The Yjs provider you choose determines how clients connect, synchronize data, and handle persistence. The best option depends on your deployment requirements, scalability needs, and whether you want to manage the infrastructure yourself.

Provider Transport Persistence Signaling/Auth Best for
y-webrtc Peer-to-peer None by default Public signaling by default; no auth Local development, demos, single-session prototypes
y-websocket WebSocket None by default You provide the server and auth Self-hosted staging and small production
Hocuspocus WebSocket Pluggable (Redis, Postgres) Token-based auth, extensions Scalable self-hosting with persistence and auth
Liveblocks Managed WebSocket Hosted Hosted auth, REST API Teams that want a fully managed backend with devtools
PartyKit Serverless on Cloudflare Optional Durable Object persistence Cloudflare auth Serverless deployments, prototypes with persistence
y-indexeddb None (local) Browser only None Offline persistence in a single browser

For production environments:

  • y-websocket offers maximum control,
  • Hocuspocus adds persistence and authentication capabilities, and
  • Liveblocks provides a managed collaboration infrastructure with minimal operational overhead.

Build it yourself or start with existing collaboration support?

When planning collaborative editing, it’s easy to underestimate how much work exists beyond the editor UI. Synchronization, conflict handling, user presence, offline recovery, and persistence often require significantly more effort than the editing experience itself.

The table below compares some of the key responsibilities involved in building a collaborative editor from scratch versus using the Syncfusion React Block Editor with Yjs.

Feature Build yourself Syncfusion + Yjs
CRDT Design and implement CRDT, merge strategies, and conflict resolution from scratch. Uses Yjs's production-tested CRDT with automatic conflict-free synchronization.
Real-time synchronization Build custom synchronization, diffing, patch generation, and nested content updates. Automatic incremental synchronization for content, properties, and document structure.
Presence & collaboration Implement cursors, selections, user awareness, and presence using custom protocols. Built-in real-time cursors, selections, user presence, and awareness through Yjs.
Provider & offline sync Build custom WebSocket messaging, offline persistence, and multi-device synchronization. Built-in WebSocket providers, offline persistence, and seamless multi-device synchronization.
Production readiness Requires validation for scalability, offline support, conflict recovery, and performance. Enterprise-ready with proven scalability, offline synchronization, and automatic recovery.

Building a collaborative editor involves much more than rendering content. By combining the Syncfusion React Block Editor with Yjs, you can focus on creating user-facing features while relying on a proven foundation for synchronization, presence, and shared editing experiences.

Building a real-time collaborative React Block Editor using Yjs

Let’s build a collaborative editor using Vite, React, TypeScript, Yjs, and the Block Editor.

Step 1: Create the project

Start by scaffolding a new React TypeScript application and installing the required packages:

npm create vite@latest collab-editor -- --template react-ts    
cd collab-editor    
npm install @syncfusion/ej2-react-blockeditor yjs y-websocket
Enter fullscreen mode Exit fullscreen mode

Step 2: Configure the editor theme

Next, replace the contents of the src/index.css file with the following imports:

src/index.css

@import "@syncfusion/ej2-base/styles/tailwind3.css"; 
@import "@syncfusion/ej2-inputs/styles/tailwind3.css"; 
@import "@syncfusion/ej2-popups/styles/tailwind3.css";
@import "@syncfusion/ej2-buttons/styles/tailwind3.css"; 
@import "@syncfusion/ej2-splitbuttons/styles/tailwind3.css";
@import "@syncfusion/ej2-navigations/styles/tailwind3.css";
@import "@syncfusion/ej2-dropdowns/styles/tailwind3.css";
@import "@syncfusion/ej2-react-blockeditor/styles/tailwind3.css";
Enter fullscreen mode Exit fullscreen mode

If your application already uses a different design system, replace tailwind3 with themes such as fluent, material, bootstrap5, material-dark, or bootstrap5-dark to match the rest of your UI.

Step 3: Create a collaboration hook

To keep the editor integration clean, create a dedicated collaboration hook. This hook manages the Y.Doc, shared Y.XmlFragment, Yjs provider, and the collaboration adapter throughout the component’s lifecycle, and automatically cleans up resources when the component is unmounted.

Refer to the code in the src/hooks/useCollaboration.ts. file

Step 4: Connect the editor

With the collaboration hook in place, the final step is to connect it to the Block Editor.

The following src/App.tsx file brings everything together by integrating the collaboration hook, rendering the editor, and displaying collaboration details such as connection status and active users. Once configured, multiple clients connected to the same room can edit the document in real-time.

Refer to the code in the src/App.tsx file and run the application.

Read the full blog post on the Syncfusion Website

Top comments (0)