### Install Trystero and WebRTC Polyfill
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/ADVANCED-TOPICS.md
Install the necessary packages for server-side Trystero usage with a WebRTC polyfill.
```bash
npm install trystero werift
```
--------------------------------
### Firebase Pre-initialized App Example
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/CONFIGURATION.md
Example of joining a room with a pre-initialized Firebase app. This avoids re-initialization and allows for more control over Firebase setup.
```javascript
import {initializeApp} from 'firebase/app'
import {joinRoom} from '@trystero-p2p/firebase'
const firebaseApp = initializeApp({
databaseURL: 'https://myproject.firebaseio.com',
// ... other config
})
const room = joinRoom({
appId: 'https://myproject.firebaseio.com',
relayConfig: {
firebaseApp
}
}, 'room-id')
```
--------------------------------
### Install Trystero with npm
Source: https://github.com/dmotz/trystero/blob/main/README.md
Install the Trystero library using npm. This is the recommended way to add Trystero to your project.
```sh
npm i trystero
```
--------------------------------
### Install WebSocket Relay Server
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/WS-RELAY-SERVER.md
Install the WebSocket relay server package using npm.
```bash
npm install @trystero-p2p/ws-relay
```
--------------------------------
### Importing Trystero
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/README.md
Examples of how to import the joinRoom function from Trystero, showing both the default Nostr strategy and the MQTT strategy.
```javascript
import {joinRoom} from 'trystero' // Default (Nostr)
```
```javascript
import {joinRoom} from '@trystero-p2p/mqtt' // MQTT strategy
```
--------------------------------
### Configuration Option Documentation Example
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/INDEX.md
Illustrates the format for documenting configuration options, including their properties, types, and descriptions. Use this for documenting any configurable setting.
```markdown
### Option Name
| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
**Example:**
```javascript
const config = {...}
```
```
--------------------------------
### Initialize Firebase and Join Room
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/STRATEGIES.md
Example demonstrating how to initialize the Firebase app and then use it to join a Trystero room. Ensure your databaseURL is correctly set.
```javascript
import {initializeApp} from 'firebase/app'
import {joinRoom} from '@trystero-p2p/firebase'
const firebaseApp = initializeApp({
databaseURL: 'https://myapp.firebaseio.com'
})
const room = joinRoom({
appId: 'https://myapp.firebaseio.com',
relayConfig: {
firebaseApp
}
}, 'room-1')
```
--------------------------------
### API Function Documentation Example
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/INDEX.md
Demonstrates the standard format for documenting exported functions, including signature, parameters, return values, and examples. Use this for documenting any public function or method.
```markdown
### functionName(param1, [param2])
**Signature:**
```typescript
function functionName(param1: Type1, param2?: Type2): ReturnType
```
**Parameters:**
| Parameter | Type | Required | Default | Description |
...
**Returns:** Description of return value
**Example:**
```javascript
// Complete working example
```
**Throws:** When errors occur
```
--------------------------------
### API Function Example
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/INDEX.md
A complete, working example illustrating the usage of an API function. This should be included in the function's documentation.
```javascript
// Complete working example
```
--------------------------------
### JoinRoomConfig Example
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/TYPES.md
Example of a JoinRoomConfig object used to configure room joining with Trystero. It includes application ID, password, passive mode, relay configuration, trickle ICE, and TURN server settings.
```typescript
const config: JoinRoomConfig = {
appId: 'my-app-id',
password: 'shared-secret-key',
passive: false,
relayConfig: {
urls: ['wss://relay1.example.com', 'wss://relay2.example.com'],
redundancy: 2
},
trickleIce: true,
turnConfig: [
{
urls: ['turn:turn.example.com:3478'],
username: 'user',
credential: 'pass'
}
]
}
```
--------------------------------
### Create a WebSocket Relay Server
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/STRATEGIES.md
Set up and start a custom WebSocket relay server for Trystero peers. Ensure the server is listening on the specified port.
```javascript
// server.ts / server.js
import {createWsRelayServer} from '@trystero-p2p/ws-relay/server'
const server = createWsRelayServer({
port: 8080
})
server.ready.then(() => {
const addr = server.address()
console.log(`Relay listening on ${addr.address}:${addr.port}`)
})
```
--------------------------------
### Join Room with IPFS Strategy
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/STRATEGIES.md
Example of joining a room using the IPFS strategy with an application ID.
```javascript
import {joinRoom} from '@trystero-p2p/ipfs'
const room = joinRoom({
appId: 'ipfs-app-v1'
}, 'room-1')
room.onPeerJoin = peerId => console.log(`${peerId} joined via IPFS`)
```
--------------------------------
### Minimal Handshake Example
Source: https://github.com/dmotz/trystero/blob/main/README.md
Demonstrates a basic handshake process between peers to verify identity before establishing a full connection. This example shows how to use `send` and `receive` within the `onPeerHandshake` callback.
```javascript
import {joinRoom} from 'trystero'
const room = joinRoom({appId: 'my-app'}, 'secure-room', {
onPeerHandshake: async (_, send, receive, isInitiator) => {
if (isInitiator) {
await send({challenge: 'prove-you-know-the-secret'})
const {data} = await receive()
if (data?.response !== 'shared-secret') {
throw new Error('handshake rejected')
}
} else {
const {data} = await receive()
if (data?.challenge !== 'prove-you-know-the-secret') {
throw new Error('handshake rejected')
}
await send({response: 'shared-secret'})
}
}
})
```
--------------------------------
### Type Usage Example
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/INDEX.md
An example demonstrating how to use a defined type. This is included in the type's documentation.
```typescript
const example: TypeName = {...}
```
--------------------------------
### Async/Await Usage Example
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/README.md
Demonstrates the use of async/await for Trystero's Promise-based APIs, common in asynchronous operations.
```javascript
const result = await action.request(data, {target: peerId})
```
--------------------------------
### Configuration Example
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/INDEX.md
A JavaScript object literal representing a configuration. This is used in the configuration documentation.
```javascript
const config = {...}
```
--------------------------------
### Join Room with MQTT Strategy
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/STRATEGIES.md
Example of joining a room using the MQTT strategy, specifying custom broker URLs. This is suitable for IoT-style deployments.
```javascript
import {joinRoom} from '@trystero-p2p/mqtt'
const room = joinRoom({
appId: 'iot-app',
relayConfig: {
urls: ['wss://broker.hivemq.com:8884/mqtt']
}
}, 'sensor-network')
```
--------------------------------
### Start Self-Hosted WebSocket Relay Server
Source: https://github.com/dmotz/trystero/blob/main/README.md
Use this to start a self-hosted WebSocket relay server on Node or Bun. Ensure the port is accessible.
```javascript
import {createWsRelayServer} from '@trystero-p2p/ws-relay/server'
createWsRelayServer({port: 8080})
```
--------------------------------
### Example PeerHandshake Implementation
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/TYPES.md
An example demonstrating how to implement the onPeerHandshake callback for custom peer authentication. This snippet shows a challenge-response mechanism to validate peers.
```typescript
const callbacks: JoinRoomCallbacks = {
onPeerHandshake: async (peerId, send, receive, isInitiator) => {
if (isInitiator) {
await send({challenge: 'secret-code'})
const {data} = await receive()
if (data?.response !== 'valid-response') {
throw new Error('handshake failed')
}
} else {
const {data} = await receive()
if (data?.challenge !== 'secret-code') {
throw new Error('invalid challenge')
}
await send({response: 'valid-response'})
}
},
handshakeTimeoutMs: 5000
}
```
--------------------------------
### Join Room with Supabase Strategy
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/STRATEGIES.md
Example of joining a room using the Supabase strategy with project URL and API key.
```javascript
import {joinRoom} from '@trystero-p2p/supabase'
const room = joinRoom({
appId: 'https://xyzabc.supabase.co',
relayConfig: {
supabaseKey: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
}
}, 'collaboration-room')
```
--------------------------------
### TurnServerConfig Example
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/TYPES.md
Example of a TurnServerConfig object for configuring a TURN server for WebRTC NAT traversal. It specifies the server URL, username, and credential.
```typescript
const turnConfig: TurnServerConfig = {
urls: 'turn:turn.example.com:3478',
username: 'alice',
credential: 'secret123'
}
```
--------------------------------
### TypeScript Type Annotation Example
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/README.md
Illustrates how TypeScript type annotations are used in examples, which are also compatible with JavaScript.
```typescript
const config: JoinRoomConfig = {appId: 'my-app'}
```
--------------------------------
### Type Documentation Example
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/INDEX.md
Shows the standard format for documenting exported types or interfaces, including their definition, properties, and usage. Use this for documenting any public type.
```markdown
### TypeName
**Type Definition:**
```typescript
type TypeName = {...}
```
**Properties:**
| Property | Type | Required | Description |
...
**Used By:** Functions that accept/return this type
**Example:**
```typescript
const example: TypeName = {...}
```
```
--------------------------------
### Nostr Custom Relay Example
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/CONFIGURATION.md
Example of joining a room with custom Nostr relay URLs. Ensure your provided URLs are valid Nostr relays.
```javascript
import {joinRoom} from 'trystero'
const room = joinRoom({
appId: 'decentralized-app',
relayConfig: {
urls: [
'wss://my-relay1.example.com',
'wss://my-relay2.example.com'
]
}
}, 'room-123')
```
--------------------------------
### Archive Node Setup with Trystero
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/ADVANCED-TOPICS.md
Set up an archive node using Trystero on a server. This node passively listens for messages and stores them. Requires a WebRTC polyfill.
```javascript
import {joinRoom} from 'trystero'
import {RTCPeerConnection} from 'werift'
const room = joinRoom({
appId: 'my-app',
rtcPolyfill: RTCPeerConnection,
passive: true // Only listen
}, 'archive')
const messages = []
const chat = room.makeAction('message')
chat.onMessage = (text, {peerId}) => {
messages.push({
timestamp: Date.now(),
peerId,
text
})
// Persist to database
saveMessage({peerId, text})
}
// Serve archived messages
app.get('/api/messages', (req, res) => {
res.json(messages)
})
```
--------------------------------
### Simple WebSocket Tracker Implementation
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/ADVANCED-TOPICS.md
An example demonstrating how to create a custom signaling strategy using WebSockets as a tracker. This implementation handles WebSocket connection, message routing, and peer signaling.
```javascript
import {createStrategy, toJson, fromJson} from '@trystero-p2p/core'
export const joinRoom = createStrategy({
init: config => {
return new Promise((resolve, reject) => {
const ws = new WebSocket(config.relayConfig.trackerUrl)
ws.onopen = () => resolve(ws)
ws.onerror = reject
})
},
subscribe: (ws, rootTopic, selfTopic, onMessage, getOffers) => {
const handler = event => {
const msg = fromJson(event.data)
const [topic, payload, signalPeer] = [
msg.topic,
msg.payload,
(peerId, signal) => onMessage(peerId, msg, (signalStr) => {
ws.send(toJson({
type: 'signal',
topic: peerId,
offer: signalStr
}))
})
]
if (msg.type === 'offer') {
onMessage(msg.peerId, msg.offer, signalPeer)
}
}
ws.addEventListener('message', handler)
return () => ws.removeEventListener('message', handler)
},
announce: async (ws, rootTopic, selfTopic, extraPayload) => {
ws.send(toJson({
type: 'announce',
topic: rootTopic,
peerId: selfId
}))
}
})
```
--------------------------------
### Relay Node Setup with Trystero
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/ADVANCED-TOPICS.md
Implement a relay node using Trystero on a server. This node echoes all received messages to other connected peers. Requires a WebRTC polyfill.
```javascript
import {joinRoom} from 'trystero'
import {RTCPeerConnection} from 'werift'
const room = joinRoom({
appId: 'relay-network',
rtcPolyfill: RTCPeerConnection
}, 'relay-1')
const broadcast = room.makeAction('broadcast')
// Echo all messages to other peers
broadcast.onMessage = (data, {peerId}) => {
const otherPeers = Object.keys(room.getPeers()).filter(id => id !== peerId)
if (otherPeers.length > 0) {
broadcast.send(data, {target: otherPeers})
}
}
```
--------------------------------
### Node.js Load Balancer Example
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/WS-RELAY-SERVER.md
Example of a Node.js load balancer using node-http-proxy to distribute WebSocket connections across multiple relay servers. It implements basic round-robin routing.
```javascript
// load-balancer.js (e.g., using node-http-proxy)
const httpProxy = require('http-proxy')
const http = require('http')
const relays = [
'http://relay1:8080',
'http://relay2:8080',
'http://relay3:8080'
]
let index = 0
const proxy = httpProxy.createProxyServer({
target: relays[index % relays.length],
ws: true
})
const server = http.createServer((req, res) => {
index++
proxy.web(req, res)
})
server.on('upgrade', (req, socket, head) => {
index++
proxy.ws(req, socket, head)
})
server.listen(80)
```
--------------------------------
### Create and Monitor Durable WebSocket Relay Server
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/WS-RELAY-SERVER.md
This JavaScript example demonstrates how to create a durable WebSocket relay server using Trystero, including basic monitoring of active clients and graceful shutdown handling.
```javascript
import {createWsRelayServer} from '@trystero-p2p/ws-relay/server'
const server = createWsRelayServer({
port: process.env.PORT || 8080,
onError: (error) => {
console.error('Server error:', error)
}
})
server.ready.then(() => {
const addr = server.address()
console.log(`WebSocket relay listening on port ${addr?.port || 8080}`)
})
// Monitor server health
setInterval(() => {
const clients = server.wss.clients.size
const topicCount = Object.keys(
// Access internal subscription map (if available via ws internals)
).length
console.log(`Active clients: ${clients}`)
}, 30000)
// Graceful shutdown
process.on('SIGTERM', async () => {
console.log('SIGTERM received, shutting down gracefully...')
// Optionally notify clients
server.publish('__system__', {
type: 'shutdown',
message: 'Server shutting down'
})
await new Promise(resolve => setTimeout(resolve, 1000))
await server.close()
process.exit(0)
})
```
--------------------------------
### Join a Trystero Room
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/API-REFERENCE.md
Use `joinRoom` to add the local user to a room. Call this with the same `roomId` to get the same room instance. Configure with `appId` and optional settings. Set up `onPeerJoin` and `onPeerLeave` callbacks for event handling. Use `room.leave()` to exit.
```javascript
import {joinRoom} from 'trystero'
const config = {appId: 'my-unique-app-id'}
const room = joinRoom(config, 'chat-room-1')
room.onPeerJoin = peerId => console.log(`${peerId} joined`)
room.onPeerLeave = peerId => console.log(`${peerId} left`)
// Later: leave the room
room.leave()
```
--------------------------------
### Obtain Let's Encrypt Certificate
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/WS-RELAY-SERVER.md
Secures a domain with a Let's Encrypt certificate for production use. Requires Certbot to be installed.
```bash
# Let's Encrypt (production)
certbot certonly --standalone -d relay.example.com
```
--------------------------------
### High-Redundancy Decentralized Setup
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/CONFIGURATION.md
Set up Trystero for a highly redundant decentralized application by increasing the number of relays and optionally including TURN servers for direct connection fallback.
```javascript
const config = {
appId: 'resilient-app',
relayConfig: {
redundancy: 10, // Connect to 10 relays instead of default 5
manualReconnection: false
},
turnConfig: [
// Add TURN for peer pairs that can't connect directly
{
urls: 'turn:turn1.cloudflare.com',
username: 'user',
credential: 'key'
}
]
}
```
--------------------------------
### React Component with Trystero Hooks
Source: https://github.com/dmotz/trystero/blob/main/README.md
Example React component demonstrating how to use Trystero hooks for real-time peer-to-peer communication, including syncing state and handling peer joins.
```jsx
import {joinRoom} from 'trystero'
import {useState} from 'react'
const trysteroConfig = {appId: 'thurn-und-taxis'}
export default function App({roomId}) {
const room = joinRoom(trysteroConfig, roomId)
const colorAction = room.makeAction('color')
const [myColor, setMyColor] = useState('#c0ffee')
const [peerColors, setPeerColors] = useState({})
// whenever new peers join the room, send my color to them:
room.onPeerJoin = peer => colorAction.send(myColor, {target: peer})
// listen for peers sending their colors and update the state accordingly:
colorAction.onMessage = (color, {peerId}) =>
setPeerColors(peerColors => ({...peerColors, [peerId]: color}))
const updateColor = e => {
const {value} = e.target
// when updating my own color, broadcast it to all peers:
colorAction.send(value)
setMyColor(value)
}
return (
<>
>
)
}
```
--------------------------------
### Handle Handshake Errors with Error Throwing
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/ERRORS.md
Demonstrates how to implement handshake logic with explicit error throwing to deny peers. This example shows both initiator and non-initiator roles and logs handshake failures.
```javascript
const room = joinRoom({appId: 'my-app'}, 'secure-room', {
onPeerHandshake: async (peerId, send, receive, isInitiator) => {
try {
if (isInitiator) {
await send({challenge: 'verify-yourself'})
const {data, metadata} = await receive()
if (data?.response !== 'correct-answer') {
throw new Error('invalid response from peer')
}
} else {
const {data} = await receive()
if (data?.challenge !== 'verify-yourself') {
throw new Error('invalid challenge')
}
await send({response: 'correct-answer'})
}
} catch (err) {
console.error(`Handshake with ${peerId} failed:`, err)
throw err // Deny the peer
}
},
handshakeTimeoutMs: 3000
})
```
--------------------------------
### Implement Custom WebSocket Pub/Sub Strategy
Source: https://github.com/dmotz/trystero/blob/main/README.md
Create a custom signaling strategy for Trystero using `createTopicStrategy`. This example demonstrates a simple WebSocket pub/sub relay. Ensure your WebSocket server handles the specified message format.
```javascript
import {createTopicStrategy, toJson} from '@trystero-p2p/core'
export const joinRoom = createTopicStrategy({
// Define init as a function that returns a promise of your signaling client.
// Resolve the promise when your client is ready to send messages.
// You can also return an array of client promises for redundancy.
// In this case, the client is a single WebSocket.
init: config =>
new Promise((resolve, reject) => {
const ws = new WebSocket(config.relayConfig.urls[0])
ws.addEventListener('open', () => resolve(ws), {once: true})
ws.addEventListener('error', reject, {once: true})
}),
// Subscribe to one topic. Trystero decides which topics are needed and when.
subscribeTopic: (client, topic, onMessage) => {
const onWsMessage = event => {
const message = JSON.parse(String(event.data))
if (message.topic !== topic) {
return
}
onMessage(message.topic, message.payload)
}
client.addEventListener('message', onWsMessage)
client.send(toJson({type: 'subscribe', topic}))
return () => {
client.send(toJson({type: 'unsubscribe', topic}))
client.removeEventListener('message', onWsMessage)
}
},
// Publish a payload to one topic.
publishTopic: (client, topic, payload) =>
client.send(
toJson({
type: 'publish',
topic,
payload
})
)
})
const room = joinRoom(
{appId: 'my-app-id', relayConfig: {urls: ['wss://my-relay.example']}},
'my-room-id'
)
```
--------------------------------
### Import Trystero Functions
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/STRATEGIES.md
Imports necessary functions from the Trystero library for room management and peer identification. This is a common setup for using Trystero.
```javascript
import {joinRoom, selfId, getRelaySockets, pauseRelayReconnection, resumeRelayReconnection} from 'trystero'
```
--------------------------------
### Join Room with BitTorrent Strategy (Passive Mode)
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/STRATEGIES.md
Example of joining a room using the BitTorrent strategy in passive (listen-only) mode. This reduces tracker load for backup nodes.
```javascript
import {joinRoom} from '@trystero-p2p/torrent'
const room = joinRoom({
appId: 'my-app',
passive: true // Listen-only node
}, 'backup-node')
```
--------------------------------
### Docker Deployment for HTTP Relay
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/WS-RELAY-SERVER.md
Dockerfile for deploying the Trystero relay server for standard HTTP WebSocket connections. Installs dependencies and copies server files.
```dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY server.js .
EXPOSE 8080
CMD ["node", "server.js"]
```
--------------------------------
### Send Data with Progress and Metadata
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/API-REFERENCE.md
Utilize the `send` method of a Trystero action object to transmit data to peers. You can specify target peers, include metadata, and monitor transfer progress with a callback. This example demonstrates sending a blob with a filename in metadata and logging progress.
```javascript
const file = room.makeAction('file')
file.send(blob, {
target: peerId,
metadata: {filename: 'document.pdf'},
onProgress: (percent, {peerId}) => {
console.log(`${percent * 100}% sent to ${peerId}`)
}
})
```
--------------------------------
### Running Trystero Server-Side with WebRTC Polyfill
Source: https://github.com/dmotz/trystero/blob/main/README.md
Demonstrates how to use Trystero in a Node.js or Bun environment by importing a WebRTC polyfill like 'werift'. This enables server-side peers for state persistence or lightweight clients.
```js
import {joinRoom} from 'trystero'
import {RTCPeerConnection} from 'werift'
const room = joinRoom(
{appId: 'your-app-id', rtcPolyfill: RTCPeerConnection},
'your-room-name'
)
```
--------------------------------
### Create Audio Chatroom with Trystero
Source: https://github.com/dmotz/trystero/blob/main/README.md
Set up local audio streams and handle incoming peer audio streams for a chatroom. Ensure `room.addStream` is called for both current and future peers.
```javascript
// this object can store audio instances for later
const peerAudios = {}
// get a local audio stream from the microphone
const selfStream = await navigator.mediaDevices.getUserMedia({
audio: true,
video: false
})
// send stream to peers currently in the room
room.addStream(selfStream)
// send stream to peers who join later
room.onPeerJoin = peerId => room.addStream(selfStream, {target: peerId})
// handle streams from other peers
room.onPeerStream = (stream, peerId) => {
// create an audio instance and set the incoming stream
const audio = new Audio()
audio.srcObject = stream
audio.autoplay = true
// add the audio to peerAudios object if you want to address it for something
// later (volume, etc.)
peerAudios[peerId] = audio
}
```
--------------------------------
### Waiting for Server Readiness
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/WS-RELAY-SERVER.md
Await the `ready` promise to ensure the server is operational before accepting connections. Handle potential startup failures by catching errors.
```javascript
const server = createWsRelayServer({port: 8080})
try {
await server.ready
console.log('Server started')
} catch (error) {
console.error('Failed to start:', error)
}
```
--------------------------------
### Firebase Security Rules Example
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/CONFIGURATION.md
Example of Firebase security rules for Trystero. These rules control read and write access to your Firebase Realtime Database for Trystero rooms.
```json
{
"rules": {
".read": false,
".write": false,
"__trystero__": {
".read": false,
".write": false,
"$room_id": {
".read": true,
".write": true
}
}
}
}
```
--------------------------------
### Create Basic WebSocket Relay Server
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/WS-RELAY-SERVER.md
Set up a basic WebSocket relay server listening on a specified port. The server's address is logged upon successful startup.
```javascript
import {createWsRelayServer} from '@trystero-p2p/ws-relay/server'
const server = createWsRelayServer({
port: 8080
})
server.ready.then(() => {
const address = server.address()
console.log(`Relay listening on ${address.address}:${address.port}`)
})
```
--------------------------------
### Join Room with Different Signaling Strategies
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/API-REFERENCE.md
Demonstrates importing the `joinRoom` function from various Trystero signaling strategy packages. Each import allows connection through a different P2P network.
```javascript
import {joinRoom} from 'trystero' // Nostr (default)
import {joinRoom} from '@trystero-p2p/mqtt' // MQTT
import {joinRoom} from '@trystero-p2p/torrent' // BitTorrent
import {joinRoom} from '@trystero-p2p/firebase' // Firebase
import {joinRoom} from '@trystero-p2p/supabase' // Supabase
import {joinRoom} from '@trystero-p2p/ipfs' // IPFS
import {joinRoom} from '@trystero-p2p/ws-relay' // WebSocket Relay
```
--------------------------------
### Getting Subscriber Counts
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/WS-RELAY-SERVER.md
Obtain the number of connected clients using `getSubscriberCount()`. Provide a topic name to get the count for a specific topic, or call without arguments for the total count.
```javascript
server.ready.then(() => {
const total = server.getSubscriberCount()
const roomACount = server.getSubscriberCount('room-a')
console.log(`Total subscribers: ${total}, Room A: ${roomACount}`)
})
```
--------------------------------
### Type Definition Example
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/INDEX.md
The TypeScript type definition for a data structure. This is part of the type documentation structure.
```typescript
type TypeName = {...}
```
--------------------------------
### Get Connection Statistics
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/ADVANCED-TOPICS.md
Retrieves connection statistics for all peers in the room. Useful for debugging connection issues.
```javascript
function getConnectionStats() {
const peers = room.getPeers()
return Object.entries(peers).map(([peerId, connection]) => ({
peerId,
state: connection.connectionState,
iceState: connection.iceConnectionState,
signalingState: connection.signalingState,
iceGatheringState: connection.iceGatheringState
}))
}
console.log(getConnectionStats())
```
--------------------------------
### Import joinRoom from CDN
Source: https://github.com/dmotz/trystero/blob/main/README.md
Import the `joinRoom` function from Trystero using a CDN. This is an alternative for projects that do not use a package manager.
```html
```
--------------------------------
### Connect to Trystero Relay Server
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/WS-RELAY-SERVER.md
Use `joinRoom` to connect to a Trystero relay server. Configure your application ID and relay server URLs. Listen for peer join events.
```javascript
import {joinRoom} from '@trystero-p2p/ws-relay'
const room = joinRoom({
appId: 'my-app-v1',
relayConfig: {
urls: [
'wss://relay.example.com:8443', // WSS (HTTPS)
'ws://relay-backup.internal:8080' // WS (internal)
]
}
}, 'collaboration-room')
room.onPeerJoin = peerId => {
console.log(`${peerId} joined`)
}
```
--------------------------------
### getSubscriberCount(topic?: string)
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/WS-RELAY-SERVER.md
Returns the number of subscribers. You can get the total number of subscribers across all topics or the count for a specific topic.
```APIDOC
## getSubscriberCount(topic?: string)
### Description
Returns the number of subscribers. If topic is provided, returns count for that topic. Otherwise returns total.
### Method
`getSubscriberCount(topic?: string)`
### Parameters
- **topic** (string) - Optional - The specific topic for which to retrieve the subscriber count. If omitted, returns the total subscriber count.
### Response
- **number**: The number of subscribers for the specified topic, or the total number of subscribers if no topic is provided.
### Request Example
```javascript
server.ready.then(() => {
const total = server.getSubscriberCount()
const roomACount = server.getSubscriberCount('room-a')
console.log(`Total subscribers: ${total}, Room A: ${roomACount}`)
})
```
```
--------------------------------
### Dynamic Track Management for Media Switching
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/ADVANCED-TOPICS.md
Illustrates how to dynamically manage media tracks, including adding a video stream, switching from a camera track to a screen track, and adding screen audio as a separate stream. This is useful for scenarios like live presentations or screen sharing with audio.
```javascript
const videoStream = new MediaStream()
room.addStream(videoStream)
// Start with camera
const cameraTrack = (await navigator.mediaDevices.getUserMedia({video: true})).getVideoTracks()[0]
room.addTrack(cameraTrack, videoStream)
// Switch to screen
const screenTrack = (await navigator.mediaDevices.getDisplayMedia({video: true})).getVideoTracks()[0]
room.replaceTrack(cameraTrack, screenTrack)
// Add screen audio as second stream
const screenAudioStream = new MediaStream()
const screenAudio = (await navigator.mediaDevices.getDisplayMedia({audio: true})).getAudioTracks()[0]
room.addTrack(screenAudio, screenAudioStream)
room.addStream(screenAudioStream, {metadata: {type: 'screen-audio'}})
```
--------------------------------
### Get Local Peer ID
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/API-REFERENCE.md
Access the `selfId` property to retrieve the unique identifier for the local peer, which is consistent across all rooms and sessions.
```javascript
import {selfId} from 'trystero'
console.log(`My peer ID: ${selfId}`)
```
--------------------------------
### API Function Signature Example
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/INDEX.md
The TypeScript signature for an API function, showing parameter types and return type. This is part of the API documentation structure.
```typescript
function functionName(param1: Type1, param2?: Type2): ReturnType
```
--------------------------------
### Add TURN Servers with turnConfig
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/CONFIGURATION.md
Extend Trystero's default STUN servers by adding your own TURN servers using the `turnConfig` array. This is useful for enabling relay connections without replacing default STUN configurations.
```javascript
const config = {
appId: 'my-app',
turnConfig: [
{
urls: ['turn:my-turn.example.com:3478', 'turn:my-turn.example.com:5349?transport=tcp'],
username: 'alice',
credential: 'secret123'
},
{
urls: 'turn:backup-turn.example.com:3478',
username: 'bob',
credential: 'secret456'
}
]
}
```
--------------------------------
### Import joinRoom from Trystero
Source: https://github.com/dmotz/trystero/blob/main/README.md
Import the `joinRoom` function from the Trystero library. This function is used to establish a connection to a room.
```js
import {joinRoom} from 'trystero'
```
--------------------------------
### Import joinRoom with different strategies
Source: https://github.com/dmotz/trystero/blob/main/README.md
Import the `joinRoom` function from different Trystero strategy packages. This allows you to choose your preferred signaling method.
```js
import {joinRoom} from '@trystero-p2p/mqtt'
// or
import {joinRoom} from '@trystero-p2p/torrent'
// or
import {joinRoom} from '@trystero-p2p/supabase'
// or
import {joinRoom} from '@trystero-p2p/firebase'
// or
import {joinRoom} from '@trystero-p2p/ipfs'
// or
import {joinRoom} from '@trystero-p2p/ws-relay'
```
--------------------------------
### Get Connected Peers in Trystero
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/API-REFERENCE.md
Retrieves a map of all connected peers, excluding the local user. Useful for iterating through and interacting with individual peer connections.
```javascript
const peers = room.getPeers()
Object.entries(peers).forEach(([peerId, connection]) => {
console.log(`Connected to ${peerId}`, connection)
})
```
--------------------------------
### joinRoom(config, roomId, [callbacks])
Source: https://github.com/dmotz/trystero/blob/main/README.md
Adds a local user to a room, enabling communication channels with other peers in the same namespace. Calling this multiple times with the same namespace returns the same room instance.
```APIDOC
## `joinRoom(config, roomId, [callbacks])`
### Description
Adds local user to room whereby other peers in the same namespace will open communication channels and send events. Calling `joinRoom()` multiple times with the same namespace will return the same room instance.
### Method
`joinRoom(config, roomId, [callbacks])`
### Parameters
#### `config` Object
- **`appId`** (string) - Required - A unique string identifying your app. For Supabase, use your project URL. For Firebase, use the `databaseURL` from your Firebase config.
- **`password`** (string) - Optional - A string to encrypt session descriptions via AES-GCM. If not set, a key derived from `appId` and `roomId` is used.
- **`passive`** (boolean) - Optional - For backup or relay peers that should listen for active peers without announcing themselves while a room is dormant.
- **`relayConfig`** (object) - Optional (required for some strategies) - Strategy-specific relay settings:
- **`urls`** (array of strings) - Optional (required for WebSocket) - Custom list of URLs for bootstrapping P2P connections (e.g., trackers, relays, brokers).
- **`redundancy`** (integer) - Optional (BitTorrent, Nostr, MQTT only) - Number of default relay endpoints to connect to simultaneously.
- **`manualReconnection`** (boolean) - Optional (Nostr and BitTorrent only) - Disables automatic pausing/resuming of reconnection attempts when the browser goes offline.
- **`supabaseKey`** (string) - Required (Supabase only) - Your Supabase project's `anon public` API key.
- **`firebaseApp`** (object) - Optional (Firebase only) - An already initialized Firebase app instance.
- **`firebasePath`** (string) - Optional (Firebase only) - Path where Trystero writes matchmaking data in your database.
- **`rtcConfig`** (object) - Optional - Custom `RTCConfiguration` for all peer connections.
- **`trickleIce`** (boolean) - Optional - Controls whether ICE candidates are sent incrementally (`true`) or bundled with SDP (`false`).
- **`turnConfig`** (array of objects) - Optional - Custom list of TURN servers to use.
- **`rtcPolyfill`** (function) - Optional - A custom `RTCPeerConnection`-compatible constructor.
#### `roomId` (string) - Required
A string to namespace peers and events within a room.
#### `callbacks` (function) - Optional
Callback function.
```
--------------------------------
### Dynamically Join Room with Different Strategies
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/STRATEGIES.md
Use this pattern to allow users to select a peer-to-peer strategy at runtime. It dynamically imports the chosen strategy package and joins a room using its specific joinRoom function.
```javascript
// User selects strategy
const strategyPackages = {
'nostr': 'trystero',
'torrent': '@trystero-p2p/torrent',
'mqtt': '@trystero-p2p/mqtt',
'firebase': '@trystero-p2p/firebase',
'supabase': '@trystero-p2p/supabase'
}
async function joinRoom(strategyName, config, roomId) {
const pkgName = strategyPackages[strategyName]
const {joinRoom: join} = await import(pkgName)
return join(config, roomId)
}
// Usage
const room = await joinRoom('nostr', {appId: 'my-app'}, 'room-1')
```
--------------------------------
### Listen for Peer Join Events
Source: https://github.com/dmotz/trystero/blob/main/README.md
Set up a callback to be notified when a new peer joins the room. The callback receives the peer's ID.
```javascript
room.onPeerJoin = peerId => console.log(`${peerId} joined`)
```
--------------------------------
### Get Relay WebSocket Connections
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/API-REFERENCE.md
Use `getRelaySockets` to obtain an object mapping relay server URLs to their active WebSocket connections. This function is only available for strategies that utilize relay servers.
```javascript
import {getRelaySockets} from '@trystero-p2p/torrent'
const sockets = getRelaySockets()
console.log(Object.keys(sockets)) // ['wss://tracker.webtorrent.dev', ...]
```
--------------------------------
### Getting Server Address Information
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/WS-RELAY-SERVER.md
Retrieve the server's bound address and port using the `address()` method. Check if the address is an object containing host and port details before logging.
```javascript
const server = createWsRelayServer({port: 8080})
server.ready.then(() => {
const addr = server.address()
if (addr && typeof addr === 'object') {
console.log(`Listening on ${addr.address}:${addr.port}`)
}
})
```
--------------------------------
### Listen for Peer Media Streams
Source: https://github.com/dmotz/trystero/blob/main/README.md
Set up a callback to handle incoming audio/video streams from other peers. The callback receives the stream and the peer's ID.
```javascript
room.onPeerStream = (stream, peerId) =>
(peerElements[peerId].video.srcObject = stream)
```
--------------------------------
### Configure TURN Server
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/ERRORS.md
Add a TURN server configuration to your Trystero app to help peers behind restrictive firewalls or NATs establish connections.
```javascript
const config = {
appId: 'my-app',
turnConfig: [
{
urls: 'turn:turn.example.com:3478',
username: 'user',
credential: 'pass'
}
]
}
```
```javascript
const config = {
appId: 'my-app',
turnConfig: [
{
urls: [
'turn:turn.cloudflare.com?transport=udp',
'turn:turn.cloudflare.com?transport=tcp'
],
username: await getCloudflareUsername(),
credential: await getCloudflareCredential()
}
]
}
```
--------------------------------
### Handling Join Errors in Trystero
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/ERRORS.md
This snippet demonstrates how to handle join errors by checking the error message within the onJoinError callback. It provides specific examples for password mismatches and connection issues.
```javascript
const room = joinRoom({appId: 'my-app'}, 'room-1', {
onJoinError: ({error, peerId}) => {
if (error.includes('password')) {
console.error('Password mismatch with', peerId)
// Notify user to verify shared secret
} else if (error.includes('connection')) {
console.error('Network issue connecting to', peerId)
// May need TURN server configuration
}
}
})
```
--------------------------------
### Get Relay Socket Connections
Source: https://github.com/dmotz/trystero/blob/main/README.md
Retrieve an object mapping relay URLs to their WebSocket connections. This is available for BitTorrent, Nostr, MQTT, and WebSocket relay types and can help diagnose connection states.
```javascript
import {getRelaySockets} from '@trystero-p2p/torrent'
console.log(getRelaySockets())
// => Object {
// "wss://tracker.webtorrent.dev": WebSocket,
// "wss://tracker.openwebtorrent.com": WebSocket
// }
```
--------------------------------
### Join Room with Nostr Strategy Configuration
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/STRATEGIES.md
Demonstrates how to join a Trystero room using the default Nostr signaling strategy. It shows how to configure the number of relays to connect to for redundancy.
```javascript
import {joinRoom} from 'trystero'
const room = joinRoom({
appId: 'my-app-v1',
relayConfig: {
redundancy: 3 // Connect to 3 relays instead of default 5
}
}, 'room-1')
room.onPeerJoin = peerId => console.log(`${peerId} joined`)
```
--------------------------------
### Send and Receive Multiple Streams Per Peer
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/ADVANCED-TOPICS.md
Demonstrates how to send both audio and screen streams to a peer and how to identify and handle incoming streams based on metadata. Ensure you have the necessary media devices (microphone, display) available.
```javascript
const audioStream = await navigator.mediaDevices.getUserMedia({audio: true})
const screenStream = await navigator.mediaDevices.getDisplayMedia({video: true})
// Send both
room.addStream(audioStream, {metadata: {type: 'microphone'}})
room.addStream(screenStream, {metadata: {type: 'screen'}})
// Receive and identify
const peerStreams = {}
room.onPeerStream = (stream, peerId, metadata) => {
if (!peerStreams[peerId]) {
peerStreams[peerId] = {}
}
const type = metadata?.type || 'unknown'
peerStreams[peerId][type] = stream
if (type === 'microphone') {
const audio = new Audio()
audio.srcObject = stream
audio.play()
} else if (type === 'screen') {
const video = document.getElementById(`screen-${peerId}`)
video.srcObject = stream
}
}
```
--------------------------------
### Processing requestMany() Results
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/ERRORS.md
Illustrates how to handle results from the requestMany() method, which returns an array of PeerResult objects instead of throwing errors. This example shows filtering results by status (fulfilled, timeout, rejected, disconnected) and logging responses.
```typescript
type PeerResult =
| {peerId: string; status: 'fulfilled'; value: R}
| {peerId: string; status: 'timeout'}
| {peerId: string; status: 'rejected'; error: Error}
| {peerId: string; status: 'disconnected'}
```
```javascript
const action = room.makeAction('poll', {
kind: 'request',
onRequest: ({question}) => question === 'ready' ? 'yes' : 'no'
})
const results = await action.requestMany(
{question: 'ready'},
{
targets: [alice, bob, charlie],
timeoutMs: 3000,
onResult: (result) => {
if (result.status === 'fulfilled') {
console.log(`${result.peerId} answered: ${result.value}`)
}
}
}
)
// Process all results
const fulfilled = results.filter(r => r.status === 'fulfilled')
const timedOut = results.filter(r => r.status === 'timeout')
const rejected = results.filter(r => r.status === 'rejected')
const disconnected = results.filter(r => r.status === 'disconnected')
console.log(`${fulfilled.length} responded, ${timedOut.length} timed out`)
```
--------------------------------
### Import Supabase Strategy
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/STRATEGIES.md
Import necessary functions for using the Supabase strategy.
```javascript
import {joinRoom, selfId} from '@trystero-p2p/supabase'
```
--------------------------------
### Import Firebase Strategy
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/STRATEGIES.md
Import the necessary functions for joining a room using the Firebase strategy.
```javascript
import {joinRoom, selfId} from '@trystero-p2p/firebase'
```
--------------------------------
### Import IPFS Strategy
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/STRATEGIES.md
Import necessary functions for using the IPFS strategy.
```javascript
import {joinRoom, selfId} from '@trystero-p2p/ipfs'
```
--------------------------------
### Import MQTT Strategy
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/STRATEGIES.md
Imports necessary functions for the MQTT signaling strategy.
```javascript
import {joinRoom, selfId, getRelaySockets} from '@trystero-p2p/mqtt'
```
--------------------------------
### Send Binary Data with Metadata
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/ADVANCED-TOPICS.md
Use `room.makeAction('file')` to create an action for sending binary data. Attach metadata to describe the file's properties like name, type, and size.
```javascript
const file = room.makeAction('file')
const blob = /* ... */
const metadata = {
name: 'document.pdf',
type: 'application/pdf',
size: blob.size
}
await file.send(blob, {metadata})
```
--------------------------------
### MQTT Broker Configuration
Source: https://github.com/dmotz/trystero/blob/main/_autodocs/CONFIGURATION.md
Configure MQTT brokers with custom URLs and redundancy. All URLs must support WebSocket (wss://). Use this for MQTT-based P2P communication.
```javascript
import {joinRoom} from '@trystero-p2p/mqtt'
const config = {
appId: 'my-app-id',
relayConfig: {
urls: ['wss://broker.emqx.io:8084/mqtt'],
redundancy: 2
}
}
```
--------------------------------
### joinRoom
Source: https://github.com/dmotz/trystero/blob/main/README.md
Joins a specified room with optional callbacks for connection events. This is the primary method for establishing a connection to a room.
```APIDOC
## joinRoom(config, roomId, [callbacks])
### Description
Joins a specified room with optional callbacks for connection events. This is the primary method for establishing a connection to a room.
### Parameters
#### Path Parameters
- **config** (object) - Required - Configuration object for the connection strategy.
- **roomId** (string) - Required - The identifier of the room to join.
- **callbacks** (object) - Optional - An object containing callback functions for various events.
```