Relay rooms
This is the “hello room”: connect two peers to a shared room and watch their presence sync live. A relay room needs no server code of your own — Silt carries the packets and nothing decides truth.
If you want a room that runs your own authoritative logic instead, start with the Quickstart; this page is the pure-relay path.
-
Install the client
@siltrun/clientis vanilla TypeScript with no framework dependency.Terminal window npm install @siltrun/client -
Join a room
joinRoomresolves once you’re connected and the join snapshot has arrived, soroom.peersis already populated with everyone else in the room.import { joinRoom } from "@siltrun/client";const room = await joinRoom("https://your-relay.example/room/lobby", {id: "alice", // stable, client-supplied identity});console.log(room.peers); // [{ id, state }] — the peers already hereThe
idis yours to choose and must be stable: reconnecting is just callingjoinRoomagain with the sameid. -
Send and receive presence
Presence is the unreliable, latest-wins lane — perfect for cursor positions, camera state, or anything you publish many times a second. Set your own state with
presence.set, and listen for everyone else’s withon("presence").// listen for other peers' latest presenceroom.on("presence", (peerId, state) => {console.log(peerId, "is at", state);});// publish your own (call this as often as you like — droppable, latest-wins)room.presence.set({ x: 10, y: 20, heading: 90 }); -
Send reliable events (optional)
When you can’t afford to drop a message — a chat line, a discrete action — use the reliable, ordered events lane.
room.on("event", (peerId, event) => {console.log(peerId, "did", event);});room.events.send({ type: "absorb", target: "bob" }); -
React to peers joining and leaving
room.on("join", (peer) => console.log(peer.id, "joined"));room.on("leave", (peerId, reason) => {// reason: "left" (clean) | "timeout" (session died)console.log(peerId, "left:", reason);}); -
Know when the connection drops (optional)
Auto-reconnect is on by default. The
statusevent tells you where the connection stands, so a drop or an unreachable relay shows up instead of silently hanging.room.on("status", (u) => {// "connecting" | "connected" | "reconnecting" | "failed" | "closed"if (u.status === "failed") showBanner("can't reach the room");});
The whole thing
Section titled “The whole thing”The client API in one block. Opened in two browser tabs (over HTTPS / a secure context), it’s a live two-peer room:
import { joinRoom } from "@siltrun/client";
const room = await joinRoom("https://your-relay.example/room/lobby", { id: "alice" });
room.on("presence", (peerId, state) => { console.log(peerId, "is at", state);});
room.presence.set({ x: 10, y: 20, heading: 90 });When you’re done, release the connection:
room.close();Next steps
Section titled “Next steps”- The two-lane model — when to use presence vs events.
- Build a multiplayer game — this surface inside one real game.
- API reference — every method, event, and option.