Server
Bun-native WebSocket server for real-time rooms, presence, storage, and Yjs collaboration. The @waits/lively-server package handles room lifecycle, authentication, CRDT storage, and Yjs document sync out of the box.
LivelyServer
The main entry point. Accepts a ServerConfig object and exposes .start() / .stop() for lifecycle control.
All config fields are optional. With zero config, the server listens on a random port at /rooms/:roomId.
ServerConfig shape:
Authentication
Implement the AuthHandler interface to authenticate WebSocket upgrade requests. Return a user object or null to reject the connection.
Example — verify a JWT from the query string:
Without an auth handler, the server falls back to userId and displayName query parameters on the WebSocket URL.
Room Callbacks
Hook into room events for logging, persistence, or custom logic. All callbacks are async-safe.
onJoin — fired when a user connects to a room:
onLeave — fired when a user disconnects:
onMessage — custom messages not handled internally:
onStorageChange — fired after CRDT ops are applied:
initialStorage — load persisted CRDT state when a room is created:
Example — persist storage to a database:
Yjs Support
The server manages a Y.Doc per room, syncing updates between clients automatically. Use these callbacks to persist and restore Yjs state.
initialYjs — load persisted Yjs state for a room:
onYjsChange — fired after a Yjs update is applied:
Example — persist Yjs to file:
Room (Server-Side)
Each room is created automatically when the first client connects. The LivelyServer exposes helper methods to interact with rooms from outside the WebSocket flow.
The RoomManager handles room creation, lookup, and automatic cleanup when rooms are empty (default: 30s timeout).
Types
All types are exported from @waits/lively-server.