Realtime rooms, without the plumbing
The shortest path
Section titled “The shortest path”Every extension ships a ready-made descriptor, so a working server-side feature is one line — see Getting started for what to do with the effects it hands back.
import { createSpace } from '@insession/space';import { pomodoroExtension } from '@insession/extension-pomodoro';
const space = createSpace({ extensions: [pomodoroExtension()] });
space.dispatch('pomodoro', 'start'); // -> [broadcast, schedule-timer]The packages
Section titled “The packages”@insession/space
The parent package. Builds a headless space out of extensions: the contract
(defineSpaceExtension), the aggregate registry, member/presence lifecycle, and
an instance (createSpace) that turns accepted actions into effect descriptors.
Performs no I/O itself.
@insession/ws-resilient-transport
A WebSocket transport that reconnects the way a deploy actually needs it to: fast on a service restart, jittered exponential backoff otherwise, and a full stop on terminal close codes.
@insession/space-state
A state store for shared rooms — members, chat, presence, plugins. Inbound messages fold through a pure reducer; side effects come back as descriptors instead of firing.
@insession/extension-chat
A server-authoritative chat state machine: message normalization, sticker allowlisting,
replies, reactions, and pins. reduce returns state plus effect descriptors —
persistence, broadcast, and bot notification are the host’s job to execute.
@insession/extension-pomodoro
A server-authoritative Pomodoro timer state machine: a pure reduce over
start/pause/skip/configure and declarations/cheers, plus restore/
persistState for the storage boundary.
@insession/extension-whiteboard
A server-authoritative Whiteboard state machine: shared free-draw strokes/shapes, plus an optional “drawing telephone” relay game with its own phase timing.
No edges between any of them. space, space-state,
ws-resilient-transport, extension-chat,
extension-pomodoro, extension-whiteboard, and
extension-watch-party are each independent — carrying bytes, holding state, and
assembling extensions are kept apart on purpose, so you can adopt any one alone. Even
space, the package that ties the state machines together, does not import any of
them: it only describes the shape (defaultState / reduce / …) they
already have. Using React? There is no binding package to install: one line of your own is the whole hook.