Skip to main content

WebSocket Events

SDD Classification: L3-Technical Authority: Engineering Team Review Cycle: Quarterly
This document provides a complete reference for all WebSocket event types, their payloads, and handling patterns for real-time collaboration.

Event Message Structure

All WebSocket messages follow a standard JSON format:
{
  "type": "operation",
  "event": "document_edit",
  "data": {
    "operation": { ... },
    "version": 15,
    "timestamp": "2025-01-07T10:30:00Z"
  },
  "client_id": "client_abc123",
  "message_id": "msg_1234567890"
}

Message Fields

FieldTypeDescription
typestringMessage category
eventstringSpecific event within category
dataobjectEvent-specific payload
client_idstringSending client identifier
message_idstringUnique message ID for deduplication

Event Categories


Document Operation Events

Insert Operation

Client sends content insertion:
{
  "type": "operation",
  "event": "document_edit",
  "data": {
    "operation": {
      "type": "insert",
      "position": 45,
      "content": "New text content",
      "author": "user_123",
      "attributes": {
        "bold": true,
        "italic": false
      }
    },
    "version": 16,
    "document_id": "doc_abc123"
  }
}

Delete Operation

Client sends content deletion:
{
  "type": "operation",
  "event": "document_edit",
  "data": {
    "operation": {
      "type": "delete",
      "position": 45,
      "length": 5,
      "author": "user_123"
    },
    "version": 17
  }
}

Format Operation

Client applies formatting:
{
  "type": "operation",
  "event": "document_edit",
  "data": {
    "operation": {
      "type": "format",
      "position": 45,
      "length": 10,
      "attributes": {
        "bold": true,
        "heading": 2
      },
      "author": "user_123"
    },
    "version": 18
  }
}

Operation Acknowledgment

Server acknowledges received operation:
{
  "type": "operation",
  "event": "operation_ack",
  "data": {
    "message_id": "msg_1234567890",
    "server_version": 18,
    "timestamp": "2025-01-07T10:30:00Z",
    "acknowledged": true
  }
}

Operation Broadcast

Server broadcasts operation to other clients:
{
  "type": "operation",
  "event": "operation_broadcast",
  "data": {
    "operation": {
      "type": "insert",
      "position": 50,
      "content": "Content from other user",
      "author": "user_456"
    },
    "version": 19,
    "transformed": true,
    "original_position": 45
  }
}

Presence Events

User Joined

When a user connects to the document:
{
  "type": "presence",
  "event": "user_joined",
  "data": {
    "user": {
      "id": "user_456",
      "name": "Jane Smith",
      "avatar_url": "https://cdn.materi.dev/avatars/user_456.jpg",
      "color": "#3b82f6"
    },
    "cursor_position": 0,
    "timestamp": "2025-01-07T10:30:00Z"
  }
}

User Left

When a user disconnects:
{
  "type": "presence",
  "event": "user_left",
  "data": {
    "user_id": "user_456",
    "timestamp": "2025-01-07T10:35:00Z"
  }
}

Cursor Update

Real-time cursor position updates:
{
  "type": "presence",
  "event": "cursor_update",
  "data": {
    "user_id": "user_456",
    "cursor": {
      "position": 157,
      "selection": {
        "start": 157,
        "end": 182
      }
    },
    "timestamp": "2025-01-07T10:30:00Z"
  }
}

Typing Indicator

Shows when a user is actively typing:
{
  "type": "presence",
  "event": "typing_indicator",
  "data": {
    "user_id": "user_456",
    "is_typing": true,
    "position": 157,
    "timestamp": "2025-01-07T10:30:00Z"
  }
}

Comment Events

Comment Added

New comment created:
{
  "type": "comment",
  "event": "comment_added",
  "data": {
    "comment": {
      "id": "comment_xyz789",
      "author_id": "user_123",
      "author_name": "John Doe",
      "content": "This section needs more detail",
      "position": {
        "start": 45,
        "end": 89
      },
      "thread_id": "thread_abc123",
      "created_at": "2025-01-07T10:30:00Z"
    }
  }
}

Comment Updated

Comment content modified:
{
  "type": "comment",
  "event": "comment_updated",
  "data": {
    "comment_id": "comment_xyz789",
    "updates": {
      "content": "Updated comment text"
    },
    "updated_by": "user_123",
    "updated_at": "2025-01-07T10:35:00Z"
  }
}

Comment Resolved

Comment thread resolved:
{
  "type": "comment",
  "event": "comment_resolved",
  "data": {
    "comment_id": "comment_xyz789",
    "thread_id": "thread_abc123",
    "resolved_by": "user_456",
    "resolved_at": "2025-01-07T10:40:00Z"
  }
}

Comment Deleted

Comment removed:
{
  "type": "comment",
  "event": "comment_deleted",
  "data": {
    "comment_id": "comment_xyz789",
    "deleted_by": "user_123",
    "deleted_at": "2025-01-07T10:45:00Z"
  }
}

System Events

Connection Acknowledgment

Sent after successful connection:
{
  "type": "system",
  "event": "connection_ack",
  "data": {
    "client_id": "client_abc123",
    "user_id": "user_123",
    "permissions": ["read", "write", "comment"],
    "document_version": 25,
    "server_time": "2025-01-07T10:30:00Z"
  }
}

Document Sync

Full document state synchronization:
{
  "type": "system",
  "event": "document_sync",
  "data": {
    "document": {
      "id": "doc_abc123",
      "version": 25,
      "content": "Complete document content...",
      "metadata": {
        "word_count": 1247,
        "last_modified": "2025-01-07T10:30:00Z"
      }
    },
    "active_users": [
      {
        "user_id": "user_123",
        "cursor_position": 45
      },
      {
        "user_id": "user_456",
        "cursor_position": 200
      }
    ]
  }
}

Error Event

Error notification:
{
  "type": "system",
  "event": "error",
  "data": {
    "error_code": "INSUFFICIENT_PERMISSIONS",
    "message": "You do not have write permissions for this document",
    "details": {
      "required_permission": "document:write",
      "user_permissions": ["document:read"]
    },
    "recoverable": false,
    "timestamp": "2025-01-07T10:30:00Z"
  }
}

Heartbeat (Ping/Pong)

Connection health check: Client sends:
{
  "type": "system",
  "event": "ping",
  "data": {
    "timestamp": 1704625800000
  }
}
Server responds:
{
  "type": "system",
  "event": "pong",
  "data": {
    "timestamp": 1704625800000,
    "server_time": 1704625800050
  }
}

Event Handling Patterns

Event Dispatcher

class EventDispatcher {
  constructor() {
    this.handlers = new Map();
  }

  on(type, event, handler) {
    const key = `${type}:${event}`;
    if (!this.handlers.has(key)) {
      this.handlers.set(key, []);
    }
    this.handlers.get(key).push(handler);
  }

  dispatch(message) {
    const key = `${message.type}:${message.event}`;
    const handlers = this.handlers.get(key) || [];

    handlers.forEach(handler => {
      try {
        handler(message.data, message);
      } catch (error) {
        console.error(`Error handling ${key}:`, error);
      }
    });
  }
}

// Usage
const dispatcher = new EventDispatcher();

dispatcher.on('operation', 'document_edit', (data) => {
  console.log('Document edited:', data.operation);
});

dispatcher.on('presence', 'user_joined', (data) => {
  console.log('User joined:', data.user.name);
});

ws.onmessage = (event) => {
  const message = JSON.parse(event.data);
  dispatcher.dispatch(message);
};

Event Batching

Handle multiple rapid events efficiently:
class EventBatcher {
  constructor(flushInterval = 50) {
    this.queue = [];
    this.flushInterval = flushInterval;
    this.timer = null;
  }

  add(event) {
    this.queue.push(event);

    if (!this.timer) {
      this.timer = setTimeout(() => this.flush(), this.flushInterval);
    }
  }

  flush() {
    if (this.queue.length === 0) return;

    const events = this.queue.splice(0);
    this.timer = null;

    // Process batched events
    this.processBatch(events);
  }

  processBatch(events) {
    // Group by type for efficient processing
    const grouped = events.reduce((acc, event) => {
      const key = event.type;
      if (!acc[key]) acc[key] = [];
      acc[key].push(event);
      return acc;
    }, {});

    // Process each group
    Object.entries(grouped).forEach(([type, typeEvents]) => {
      this.processEventGroup(type, typeEvents);
    });
  }
}

Event Reference Table

TypeEventDirectionDescription
operationdocument_editC→SClient edits document
operationoperation_ackS→CServer acknowledges operation
operationoperation_broadcastS→CBroadcast operation to others
presenceuser_joinedS→CUser connected
presenceuser_leftS→CUser disconnected
presencecursor_updateBidirectionalCursor position change
presencetyping_indicatorBidirectionalTyping status
commentcomment_addedBidirectionalNew comment
commentcomment_updatedBidirectionalComment modified
commentcomment_resolvedBidirectionalComment resolved
commentcomment_deletedBidirectionalComment removed
systemconnection_ackS→CConnection established
systemdocument_syncS→CFull state sync
systemerrorS→CError notification
systempingC→SClient heartbeat
systempongS→CServer heartbeat response


Document Status: Complete Version: 2.0