Loro (CRDT) Collaboration

Real-time collaboration using Loro CRDTs

Loro is a high-performance CRDT library that enables real-time collaboration with automatic conflict resolution. The @rowsncolumns/loro package provides a React hook for integrating Loro with your spreadsheet.

Installation

yarn add @rowsncolumns/loro loro-crdt

Quick Start

import { useLoro } from "@rowsncolumns/loro";
import { LoroDoc } from "loro-crdt";

// Create a Loro document
const loroDoc = new LoroDoc();

function SpreadsheetEditor() {
  const [sheetData, setSheetData] = useState({});
  const [sheets, setSheets] = useState([]);
  const [tables, setTables] = useState([]);
  const [sheetId, setSheetId] = useState(1);
  const [activeCell, setActiveCell] = useState({ rowIndex: 1, columnIndex: 1 });

  const { onBroadcastPatch, users, synced, isLeader, importUpdate } = useLoro({
    doc: loroDoc,
    userId: "user-123",
    title: "John Doe",
    sheetId,
    activeCell,
    initialSheets: [],
    onChangeSheetData: setSheetData,
    onChangeSheets: setSheets,
    onChangeTables: setTables,
    onChangeActiveSheet: setSheetId,
    calculateNow,
    enqueueGraphOperation: (op) => {
      // Handle dependency graph updates for formula recalculation
    },
    onSyncUpdate: (update) => {
      // Send update to server
      websocket.send(update);
    },
  });

  // Pass onBroadcastPatch to useSpreadsheetState
  return <Spreadsheet sheetData={sheetData} sheets={sheets} users={users} />;
}

Integration with useSpreadsheetState

Connect the Loro adapter to your spreadsheet state:

Setting Up a Loro Sync Server

Basic Server

Create a file server.ts:

Install dependencies:

Run the server:

Server with Redis Persistence

For production environments, persist Loro snapshots to Redis:

Server with PostgreSQL Persistence

Document Structure

The Loro document stores all spreadsheet data:

Cell Key Format

Cell keys follow the pattern ${sheetId}!${A1Address}:

Key
Description

"1!A1"

Cell A1 on sheet 1

"2!B5"

Cell B5 on sheet 2

"1!AA100"

Cell AA100 on sheet 1

CellDataV3 Structure

Each cell value is stored with its position metadata:

Presence Awareness

The hook automatically manages presence, allowing you to display other users' cursor positions:

Each user in the users array includes:

Leader Election

The adapter automatically elects a leader among connected clients. The leader is responsible for coordinating recalculation operations.

Offline Support

Loro CRDTs work fully offline. Changes are stored locally and automatically merged when reconnecting:

Error Handling

Handle errors with the onError callback:

Why Loro for Spreadsheets?

Loro's CRDTarrow-up-right approach offers unique advantages for spreadsheet collaboration.

Comparison with ShareDB

Aspect
Loro (CRDT)
ShareDB (OT)

Conflict Resolution

Automatic merge, eventual consistency

Server determines canonical order

Server Required

Optional (can sync peer-to-peer)

Yes

Offline Support

Full offline-first support

Requires server connection

Performance

Rust core compiled to WASM

Pure JavaScript

Recalculation

Leader election for coordination

Leader election for coordination

History

Built-in version history and time travel

Manual operation log

Data Persistence

Any storage (Redis, PostgreSQL, S3, etc.)

MongoDB, PostgreSQL via adapters

Why CRDTs Work Well for Spreadsheets

  1. Cell-level granularity - The V3 flat map structure ("sheetId!A1" keys) maps perfectly to Loro's Map CRDT. Each cell is independent, minimizing conflicts.

  2. Offline-first - Users can work without connectivity and sync later. All changes are preserved and merged automatically.

  3. High performance - Loro's Rust core provides excellent performance for large documents and many concurrent operations.

  4. Flexible architecture - No central server required. Can use WebSocket, WebRTC, or any transport.

  5. Built-in history - Time travel and version history are built into the CRDT.

When to Choose Loro

  • Need offline-first capabilities

  • Want high-performance CRDT operations

  • Need flexible sync (WebSocket, WebRTC, etc.)

  • Decentralized architecture is preferred

  • Need built-in version history

When to Choose ShareDB

  • Need traditional client-server architecture

  • Want to leverage existing MongoDB/PostgreSQL infrastructure

  • Prefer OT semantics for conflict resolution

  • Need server-side authority for all operations

Last updated