My App
BoardKitBackend

Realtime Gateway

Socket.IO WebSocket gateway for realtime collaboration

The BoardGateway is a NestJS WebSocket gateway using Socket.IO. It handles the realtime collaboration protocol defined in @hfu.digital/boardkit-core.

Gateway Configuration

@WebSocketGateway({ namespace: '/board' })
class BoardGateway implements OnGatewayConnection, OnGatewayDisconnect { }

The gateway listens on the /board namespace. Connect your Socket.IO client to ws://your-server/board.

Message Handlers

join

Authenticates the client, joins the collaboration session, and sends sync data.

  1. Validates the token via BoardAuthGuard.validateConnection()
  2. Checks access via PermissionService.checkAccess() (requires viewer role)
  3. Determines the user's effective role (viewer, editor, or owner)
  4. Joins the Socket.IO room for the board
  5. Calls CollaborationService.joinSession()
  6. Sends joined message with participant list
  7. Sends either sync:delta or sync:full based on reconnection state
  8. Broadcasts participant:joined to other clients

mutate

Applies element mutations from editors.

  1. Checks the client's role (requires editor or higher)
  2. Calls CollaborationService.applyMutations()
  3. Sends mutation:ack to the sender
  4. Broadcasts mutation:broadcast to all other clients in the room

cursor

Broadcasts cursor position to other participants.

  1. Updates the cursor in PresenceManager
  2. Broadcasts cursor:broadcast to all other clients

ping

Responds with a pong message containing the server timestamp. Useful for latency measurement.

Disconnection

When a client disconnects:

  1. Calls CollaborationService.leaveSession() to remove the participant
  2. Removes the participant from PresenceManager
  3. Broadcasts participant:left to remaining clients
  4. Cleans up internal client-to-board/user/role mappings

Supporting Services

PresenceManager

Tracks which participants are in each board session and their cursor positions.

class PresenceManager {
    addParticipant(boardId: string, participant: Participant): void;
    removeParticipant(boardId: string, userId: string): void;
    updateCursor(boardId: string, userId: string, position: Point, pageId: string): void;
    getParticipants(boardId: string): Participant[];
}

SyncRelay

Manages Socket.IO room broadcasting with exclusion support.

class SyncRelay {
    registerClient(clientId: string, socket: Socket, boardId: string): void;
    broadcast(boardId: string, message: ServerMessage, excludeClientId?: string): void;
}

ReconnectionHandler

Handles delta and full sync delivery to reconnecting clients.

class ReconnectionHandler {
    sendDelta(client: Socket, mutations: ElementMutation[], fromSeq: number, toSeq: number): Promise<void>;
    sendFullSync(client: Socket, boardId: string, currentSequence: number): Promise<void>;
}

Error Codes

CodeWhenAction
AUTH_FAILEDToken validation failsClient disconnected
FORBIDDENInsufficient permissions (e.g., viewer tries to mutate)Error message sent
SESSION_MISMATCHStale session detectedError message sent

On this page