Relays and the PeerJS transport
peerjsTransport() connects peers over WebRTC. A PeerJS relay (a signaling server) introduces them: it forwards connection offers between browsers until they can talk directly.
import { peerjsTransport } from "@vaultys/peer-sdk/peerjs";
const transport = peerjsTransport(); // the free public PeerJS cloud
What the relay sees
Each peer registers under the SHA-256 hash of its DID. The relay sees those hashes, who tries to reach whom, and the handshake frames. It never sees message content, and it can't impersonate a peer or tamper with traffic (see Security model). It can, however, see metadata and refuse service. That's the main reason to run your own.
Running your own relay
The official server is the peer package:
npx peer --port 9000
Point the transport at it:
const transport = peerjsTransport({
host: "relay.example.com",
port: 443,
path: "/",
secure: true,
});
The public cloud is fine for demos, but it's shared, rate-limited, and comes with no availability guarantee. Run your own for anything real.
TURN for restrictive networks
WebRTC tries a direct connection first. Behind strict NATs or corporate firewalls, it needs a TURN server to relay the encrypted traffic. Pass ICE servers through PeerJS's config:
const transport = peerjsTransport({
host: "relay.example.com",
secure: true,
config: {
iceServers: [
{ urls: "stun:stun.example.com:3478" },
{ urls: "turn:turn.example.com:3478", username: "user", credential: "secret" },
],
},
});
Traffic through TURN stays end-to-end encrypted by the session.
Options
peerjsTransport(options) accepts every PeerJS option (host, port, path, secure, key, config…) plus:
| Option | Default | Description |
|---|---|---|
addressOf(did) | hex SHA-256 of the DID | How a DID maps to a PeerJS id |
timeoutMs | 15000 | Timeout for registering with the relay and for dialing |
log(message) | none | Called on registration changes: drops, recoveries, retries |
const transport = peerjsTransport({ host: "relay.example.com", log: (m) => console.info("[relay]", m) });
Staying registered
The transport keeps its relay registration alive. When the signaling connection drops, it reconnects with backoff (1 s up to 30 s). It also checks every 10 seconds, when the browser comes back online, and when the tab becomes visible again, which covers sleeping laptops and frozen background tabs.
Open sessions don't depend on the relay, so they keep working through a relay outage. New connections wait until the registration is back: dialing in the meantime fails with UNREACHABLE, and queued messages are retried.
If you reload a page, its previous registration may still be held by the relay for a moment. Registration retries until it's released, within timeoutMs.