Docs
Connections and room access
Finding a peer and connecting to it are separate steps. Here’s how to handle networks that block direct connections and decide who can join.
When peers cannot connect
First check that both peers use the same app ID, room ID, strategy, password, and compatible library version. Try two tabs on one machine, then devices on different networks. If only some network pairs fail, configure a TURN server to relay their encrypted WebRTC traffic.
const room = joinRoom(
{
appId: 'com.example.calls',
turnConfig: [{
urls: 'turn:turn.example.com:3478',
username: turnUsername,
credential: turnCredential
}]
},
callId,
{
onJoinError: ({peerId, error}) => {
showConnectionError(peerId, error)
}
}
)
Fetch your TURN credentials from your app’s backend or credential service.
turnConfig adds TURN servers alongside Trystero’s default
STUN servers. To replace the full list, set
rtcConfig.iceServers instead.
Pass onJoinError in the third argument to
joinRoom(). It reports password mismatches, handshake
failures, and cases where peers exchange signaling but cannot establish
WebRTC. It does not guarantee a callback for every relay outage or an
empty room. Give users a visible waiting state as well.
Encryption and access
WebRTC encrypts messages and media between peers, including when TURN relays the traffic. Trystero also encrypts session descriptions on signaling services. By default that key comes from the app and room IDs, so anyone who knows those IDs can derive it.
A shared password adds a secret to the signaling key. All
peers must know it ahead of time. This restricts joining to people with
the secret; it does not identify an individual user.
const room = joinRoom(
{appId: 'com.example.calls', password: sharedSecret},
callId
)
For your own authentication protocol, use
onPeerHandshake(peerId, send, receive, isInitiator) in the
callbacks object. It runs after transport connection and before the peer
becomes active. Resolve to accept or throw to deny; the default timeout
is 10 seconds. See the
joinRoom reference
for the full contract.
Keep rooms small
A room connects peers to each other rather than routing everything through one media server. Connection counts, outgoing bandwidth, and device limits grow with room size. Test on the devices and networks you expect users to have; there is no single room-size limit that suits every app.
Trystero does not provide durable storage, offline delivery, or conflict resolution. Add those in your app when you need them. For large video meetings, evaluate a media server that forwards streams.
Run a backup peer on a server
Node, Bun, and Deno need an RTCPeerConnection implementation
passed through rtcPolyfill. Passive rooms stay dormant until
they discover an active peer, and do not connect to other passive peers.
This can suit a backup peer that implements persistence in your app.
const backup = joinRoom(
{
appId: 'com.example.notes',
passive: true,
rtcPolyfill: RTCPeerConnectionPolyfill
},
documentId
)
See the server-side setup
for the polyfill configuration. room.isPassive() reports
whether the room was joined in passive mode.