API reference
The complete public surface of @silt/client. This is the locked API — every
example on this site uses exactly these names.
import { joinRoom } from "@silt/client";joinRoom(url, options)
Section titled “joinRoom(url, options)”function joinRoom(url: string, options: JoinOptions): Promise<Room>;Connects to a room and resolves a Room. The promise resolves only
after the join snapshot has arrived, so room.peers is already populated with
everyone else in the room the instant joinRoom returns.
const room = await joinRoom("https://demo.silt.run/room/graveyard", { id: "alice",});url is the WebTransport URL of the room (an https:// origin plus the room
path).
JoinOptions
Section titled “JoinOptions”interface JoinOptions { id: string; certHash?: string; reconnect?: boolean; snapshotTimeoutMs?: number;}| Option | Type | Default | Description |
|---|---|---|---|
id |
string |
(required) | Stable, client-supplied identity. Reconnecting = calling joinRoom again with the same id. |
certHash |
string |
— | SHA-256 cert hash (hex) to pin via serverCertificateHashes, for local/dev secure contexts. See Run your own. |
reconnect |
boolean |
true |
Auto-reconnect with the same id on transport loss. |
snapshotTimeoutMs |
number |
5000 |
How long to wait for the join snapshot before joinRoom rejects. |
The object returned by joinRoom.
Properties
Section titled “Properties”room.url; // readonly string — the room URL you connected toroom.id; // readonly string — your stable identityroom.peers; // Peer[] — the OTHER peers in the room, populated on joinroom.peers holds the other peers and their latest presence. It’s kept in sync
as peers join, leave, and update presence. It does not include yourself.
room.presence.set(state)
Section titled “room.presence.set(state)”room.presence.set(state: PeerState): void;Publishes your latest presence on the unreliable, latest-wins datagram lane. Call it as often as you like. If the connection isn’t ready (before connect or between reconnects) the call is a harmless no-op — the last value you set is re-published automatically on reconnect. Write failures are ignored (the lane is droppable by design).
room.presence.set({ x: 10, y: 20, heading: 90 });room.events.send(event)
Section titled “room.events.send(event)”room.events.send(event: RoomEvent): Promise<void>;Sends a discrete message on the reliable, ordered lane. Returns the write
promise. Throws "room not connected" if the room isn’t currently connected,
so a critical message can’t be silently dropped.
room.events.send({ type: "absorb", target: "bob" });room.on(type, callback)
Section titled “room.on(type, callback)”room.on(type, callback): () => void;Subscribes to a room event. Returns an unsubscribe function — call it to remove the listener.
const off = room.on("presence", (peerId, state) => { /* ... */ });off(); // stop listening| Event | Callback signature | Fires when |
|---|---|---|
"presence" |
(peerId: string, state: PeerState) => void |
another peer publishes presence. |
"event" |
(peerId: string, event: RoomEvent) => void |
another peer sends a reliable event. |
"join" |
(peer: Peer) => void |
a new peer joins the room. |
"leave" |
(peerId: string, reason: LeaveReason) => void |
a peer leaves. reason is "left" (clean) or "timeout". |
room.close()
Section titled “room.close()”room.close(): Promise<void>;Cleanly leaves the room: sends a bye (so others see leave with reason
"left") and closes the transport. Disables auto-reconnect.
await room.close();type PeerState = unknown;type RoomEvent = unknown;type LeaveReason = "left" | "timeout";
interface Peer { id: string; state: PeerState | null; // null until the peer has sent presence}PeerState and RoomEvent are unknown — they’re whatever you put in them.
Define your own shapes and narrow on the way out:
interface Cursor { x: number; y: number; heading: number }
room.presence.set({ x, y, heading } satisfies Cursor); // your own shaperoom.on("presence", (peerId, state) => { const cursor = state as Cursor;});- Quickstart — the surface in a working example.
- Wire protocol — what these calls put on the wire.