Guide

WebRTC without your own signaling server

WebRTC needs a way for peers to find each other before they can connect. Trystero uses existing signaling services for that step, so you can start with client code.

What "without a signaling server" means

A WebRTC connection still starts with signaling: peers exchange connection offers, answers, and network candidates. In many apps, that signaling is a WebSocket service the app maintains.

Trystero sends those details through a signaling strategy, using public Nostr relays by default. Messages and media then travel over WebRTC, independently of the signaling service. That is what “serverless” means here: you can use infrastructure that already exists.

The basic pattern

Give your app a unique appId. Peers join the same room and create the same action names. This sketch sends pointer positions; drawing and rendering strokes are your app’s responsibility.

import {joinRoom} from 'trystero'

const room = joinRoom({appId: 'com.example.whiteboard'}, documentId)
const draw = room.makeAction('draw')

draw.onMessage = (stroke, {peerId}) => {
  renderRemoteStroke(peerId, stroke)
}

canvas.onpointermove = event => {
  draw.send({
    x: event.clientX,
    y: event.clientY,
    pressure: event.pressure
  })
}

When to bring your own relay

Public relays make it easy to try an idea. If your app depends on a particular uptime target or needs private infrastructure, choose a signaling service you can operate or monitor.

The WebSocket relay package includes a server you can host. Install the package and point clients at your secure WebSocket endpoint. The room and action API stays the same.

import {joinRoom} from '@trystero-p2p/ws-relay'

const room = joinRoom(
  {
    appId: 'com.example.whiteboard',
    relayConfig: {
      urls: ['wss://relay.example.com']
    }
  },
  documentId
)

What about TURN?

Signaling introduces peers; TURN carries encrypted WebRTC traffic when their networks prevent a direct connection. Public signaling relays do not provide that fallback. For a shipped app, test across networks and configure TURN where needed.