Getting Started

Installation

pnpm add @vuer-ai/vuer-rtc

Claude Code Skill

Add vuer-rtc knowledge to Claude Code for intelligent assistance with the library:

Option 1: Plugin Marketplace (Recommended)

# Add the marketplace (one-time setup)
/plugin marketplace add vuer-ai/vuer-rtc-workspace

# Install the skill
/plugin install vuer-rtc@vuer-rtc

Option 2: CLAUDE.md Import

Add to your project's CLAUDE.md:

@import https://raw.githubusercontent.com/vuer-ai/vuer-rtc-workspace/main/skill/vuer-rtc.md

After installation, Claude Code will have access to:

  • vuer-rtc skill — CRDT operations, client state, React hooks, and text collaboration
  • Context-aware assistance for scene graph operations

To verify installation:

/plugin list

The skill uses hierarchical documentation — Claude loads a structured overview first, then fetches detailed docs as needed for specific operations.

Quick Start

import { createGraph } from '@vuer-ai/vuer-rtc';

// Create a graph store
const store = createGraph({
  sessionId: 'my-session',
  onSend: (msg) => websocket.send(msg),
});

// Edit (uncommitted, updates UI immediately)
store.edit({
  otype: 'node.insert',   // Learn about all [Operations](/operations)
  key: 'scene',           // Parent node's key
  path: 'children',
  value: { key: 'cube', tag: 'Mesh', name: 'Cube' },
});

// Commit (sends to server as one message)
store.commit('Create cube');

// Receive from server
websocket.onmessage = (msg) => store.receive(msg);

// Undo/redo (synced across all clients)
store.undo();
store.redo();

Core Concepts

State Model

The client maintains four key data structures:

interface ClientState {
  graph: SceneGraph;       // Current computed state
  journal: JournalEntry[]; // Committed messages
  edits: EditBuffer;       // Uncommitted operations
  snapshot: Snapshot;      // Checkpoint for fast replay
}
ComponentPurpose
graphCurrent state shown in UI. Derived from snapshot + journal + edits.
journalCommitted messages. Tracks ack status and deletion (undo) state.
editsUncommitted ops. Merged during gestures, committed as one message.
snapshotPeriodic checkpoint. Bakes in acked entries for fast replay.

Edit Buffer

Operations are accumulated in the edit buffer during gestures (like dragging), then committed as a single message:

// During drag (60fps)
store.edit({ otype: 'vector3.add', key: 'cube', path: 'position', value: [0.1, 0, 0] });
store.edit({ otype: 'vector3.add', key: 'cube', path: 'position', value: [0.1, 0, 0] });
// ... many more

// On drag end - all edits become ONE message
store.commit('Move cube');
// Sends: { ops: [{ otype: 'vector3.add', value: [5.0, 0, 0] }] }

The edit buffer merges additive operations, so 60 small deltas become 1 message.

Messages & Operations

Changes are expressed as messages containing one or more operations:

interface CRDTMessage {
  id: string;           // Unique message ID
  sessionId: string;    // Who sent this
  clock: VectorClock;   // For causal ordering
  lamportTime: number;  // For LWW ordering
  timestamp: number;    // Wall clock
  ops: Operation[];     // Batch of operations
}

Undo / Redo

Undo and redo are synced messages that mark entries with deletedAt:

// Undo the last committed message from this session
const { msg } = store.undo();
// Creates: { ops: [{ otype: 'meta.undo', targetMsgId: 'msg-123' }] }
// Syncs to all clients - everyone sees the undo

// Redo the last undone message
store.redo();
// Creates: { ops: [{ otype: 'meta.redo', targetMsgId: 'msg-123' }] }

All clients see the same undo state. Undo is not local-only.

Conflict Resolution

OperationMerge StrategyExample
*.setLast-Write-Wins (higher lamport)color.set '#ff0000'
*.addSum valuesvector3.add [1, 0, 0]
meta.undoSets deletedAt on targetSynced undo
meta.redoClears deletedAt on targetSynced redo

Next Steps


Next: See the Complete Integration Guide and Examples to build your first collaborative application.