WebRTC Signaling with Signal-Fire

WebRTC Signaling with Signal-Fire

WebRTC is a technology which allows individual peers to talk directly to each other. This requires a signaling server.

A WebRTC signaling server communicates between peers to set up peer-to-peer audio/video and/or data channels. This allows your clients to communicate directly with each other.

Years ago I developed signal-fire, a WebRTC signaling server built for node.js. There also was a browser client available which greatly reduced the burden of setting up peer connections. Lack of maintenance led to the module’s eventual demise and I recently officially retired it.

Luckily I had some inspiration for the new and improved version, and I got to work. The result was the Signal-Fire ecosystem, starting with Signal-Fire Server, a server that does exactly the same as its predecessor did, but better!

The Server

Signal-Fire Server is based on my other quite recent module Luce. Luce is a versatile WebSocket framework for node.js. An excellent pairing for my new project.

Command-Line Interface (CLI)

If you want to get started with Signal-Fire Server without too much hassle, and you’re content with the basic features (for now), you can use the CLI to start and manage Server workers.

Install the CLI globally:

> npm i -g @signal-fire/cli

To start a worker on port 3003:

> signal-fire start -p 3003

Starting the Server

The Server can be installed through npm:

> npm i @signal-fire/server

To manage client IDs the Server requires a registry. In the example below we use LocalRegistry, an in-memory store.

import { Server } from 'http'

import createApp from './index'
import { LocalRegistry } from '@lucets/registry'

const registry = new LocalRegistry()
const app = createApp(registry)
const server = new Server()

server.on('upgrade', app.onUpgrade())
server.listen(3003, () => {
  console.log('Server listening on port 3003')

Congratulations, you now have a basic server running!

The Client

Signal-Fire Client is the replacement of signal-fire-client, which has also been deprecated. The Client is also new and improved. The Client is designed for the browser and uses the native EventTarget.

The Client is meant to be used with browserify.

Install the client through npm:

> npm i @signal-fire/client

Connecting to the Server is exceedingly simple:

import connect from '@signal-fire/client'

const client = await connect('ws://localhost/socket')


Sessions are requests and responses for setting up the peer connection. One peer creates a session, which its target can either accept or deny.

This example shows how to start a session:

import connect, { PeerConnection } from '@signal-fire/client'

async function run () {
  const client = await connect('ws://localhost:3003/socket')
  const session = await client.createSession('<target id>')

  session.addEventListener('accepted', (ev: CustomEvent<PeerConnection>) => {
    console.log('Session accepted!')

    const connection = ev.detail
    const stream = await navigator.mediaDevices.getUserMedia({
      video: true,
      audio: true

    stream.getTracks().forEach(track => connection.addTrack(track, stream))

  session.addEventListener('rejected', () => {
    console.log('Session rejected')

  session.addEventListener('timed-out', () => {
    console.log('Session timed out')

This example shows how to accept a session:

import connect, { IncomingSession } from '@signal-fire/client'

async function run () {
  const client = await connect('ws://localhost:3003/socket')

  client.addEventListener('session', (ev: CustomEvent<IncomingSession>) => {
    const session = ev.detail
    const connection = await session.accept()


The Signal-Fire Server and Client are projects I intent to keep maintaining, and using myself. If you’ve checked out either and found a bug, please open an issue on GitHub, or better yet, a pull request.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.