End of Life for Twilio Programmable Video - Upgrade to VideoSDKLearn More

How to Build Briefing WebRTC App with JavaScript?

Learn how to set up, implement, and test a Briefing WebRTC application using Node.JS, Simple-Peer, and an iOS client.

Introduction to Briefing WebRTC Technology

What is Briefing WebRTC?

Briefing WebRTC is an innovative technology solution designed to facilitate real-time communication through web-based video conferencing. Built on a robust technology stack that includes Node.JS for server-side logic, Simple-Peer for establishing peer-to-peer connections on the web, and an iOS client for mobile access, Briefing WebRTC leverages the capabilities of WebRTC (Web Real-Time Communication) to enable seamless, high-quality video interactions.

Key Feature of Briefing WebRTC

One of the key features of Briefing WebRTC is its use of a mesh conference server. Unlike traditional centralized servers, a mesh conference server allows each participant to connect directly to every other participant in the conference. This peer-to-peer approach reduces latency, enhances privacy, and improves the overall efficiency of the network by distributing the load across multiple nodes.
With Briefing WebRTC, developers can create scalable and flexible video conferencing applications that are capable of handling multiple participants simultaneously. The technology is particularly suited for scenarios where low latency and high performance are critical, such as in business meetings, online education, telemedicine, and social networking.
In this article, we will guide you through the process of setting up a Briefing WebRTC application from scratch. We will cover the essential steps, from creating a new project and installing necessary dependencies, to structuring the project, implementing key features, and finally, running and testing your application. By the end of this guide, you will have a functional Briefing WebRTC app that demonstrates the power and versatility of this technology.

Getting Started with the Code

Create a New Briefing WebRTC App

To get started with Briefing WebRTC, the first step is to create a new project. This involves setting up the necessary development environment and initializing a new Node.JS application. Here’s how you can do it:

[a] Install Node.JS

Ensure you have Node.JS installed on your system. You can download it from the

official Node.JS website


[b] Initialize a New Project

Create a new directory for your project and navigate into it using the command line. Then, initialize a new Node.JS project using the following commands:


1    mkdir briefing-webrtc-app
2    cd briefing-webrtc-app
3    npm init -y
This will create a package.json file in your project directory.

[c] Install Necessary Dependencies

Next, you need to install the dependencies required for your Briefing WebRTC application. The primary libraries you’ll be using are simple-peer for WebRTC functionality and express to set up a basic server. Run the following command to install these dependencies:


1npm install express simple-peer

Structure of the Project

Organizing your project files properly is crucial for maintaining clean and manageable code. Here’s a recommended directory structure for your Briefing WebRTC app:
23├── public/
4│   ├── index.html
5│   └── main.js
6├── server/
7│   └── server.js
8├── package.json
9└── README.md
  • public/ directory will contain the client-side code, including HTML and JavaScript files.
  • server/ directory will contain the server-side code.

App Architecture

Briefing WebRTC
The architecture of your Briefing WebRTC app involves setting up a Node.JS server to handle signaling and establishing peer-to-peer connections using Simple-Peer. Here’s a high-level overview:
  1. Node.JS Server: This server will handle client connections and facilitate signaling between peers.
  2. Simple-Peer: This library will manage peer-to-peer connections, enabling video and audio communication between clients.
By setting up this architecture, you ensure that your app is scalable and can handle multiple participants efficiently. With the basic setup complete, we can now proceed to the next steps: setting up the main file, wiring the components, and implementing the core features of the application.

Step 1: Get Started with Main File

Setting Up the Main File

The main file of your Briefing WebRTC application serves as the entry point for your server. It will handle setting up the server, serving static files, and managing WebSocket connections for signaling. Let's create and configure this file.

[a] Create the Main Server File

Navigate to the server directory and create a file named server.js.


1   cd server
2   touch server.js

[b] Set Up the Server

Open server.js in your preferred text editor and add the following code to set up an Express server:


1   const express = require('express');
2   const http = require('http');
3   const path = require('path');
4   const { Server } = require('socket.io');
6   const app = express();
7   const server = http.createServer(app);
8   const io = new Server(server);
10   // Serve static files from the public directory
11   app.use(express.static(path.join(__dirname, '../public')));
13   // Handle a simple get request
14   app.get('/', (req, res) => {
15       res.sendFile(path.join(__dirname, '../public/index.html'));
16   });
18   // WebSocket connection for signaling
19   io.on('connection', (socket) => {
20       console.log('a user connected');
22       socket.on('disconnect', () => {
23           console.log('user disconnected');
24       });
26       socket.on('signal', (data) => {
27           io.to(data.to).emit('signal', data);
28       });
30       socket.on('join', (room) => {
31           socket.join(room);
32           socket.to(room).emit('new user', socket.id);
33       });
34   });
36   // Start the server
37   const PORT = process.env.PORT || 3000;
38   server.listen(PORT, () => {
39       console.log(`Server is running on port ${PORT}`);
40   });

[c] Explanation

  • Express Server: The Express server serves static files from the public directory and handles HTTP requests.
  • WebSocket Setup: Using socket.io, it manages WebSocket connections for signaling between peers.
  • Event Handling: The server listens for signal and join events, facilitating communication between clients.
With your main server file set up, the foundation of your Briefing WebRTC application is in place. The next step involves wiring all the components and creating the user interface, starting with the wireframe and then implementing specific features like the join screen and user controls.

Step 2: Wireframe All the Components

Creating the Wireframe

To begin implementing the client-side of your Briefing WebRTC application, you'll need to create the wireframe. The wireframe includes the basic structure of the user interface, such as the join screen and the main conference area. This step will set up the HTML and JavaScript files that will manage the user interactions and WebRTC functionalities.

[a] Create the HTML File

In the public directory, create an index.html file with the following content:


1   <!DOCTYPE html>
2   <html lang="en">
3   <head>
4       <meta charset="UTF-8">
5       <meta name="viewport" content="width=device-width, initial-scale=1.0">
6       <title>Briefing WebRTC</title>
7       <link rel="stylesheet" href="styles.css">
8   </head>
9   <body>
10       <div id="join-screen">
11           <h1>Join a Conference</h1>
12           <input type="text" id="room-input" placeholder="Enter room name">
13           <button id="join-button">Join</button>
14       </div>
15       <div id="conference-screen" style="display:none;">
16           <h1>Conference Room</h1>
17           <div id="local-video-container"></div>
18           <div id="remote-video-container"></div>
19           <button id="leave-button">Leave</button>
20       </div>
21       <script src="/socket.io/socket.io.js"></script>
22       <script src="https://cdn.jsdelivr.net/npm/simple-peer/simplepeer.min.js"></script>
23       <script src="main.js"></script>
24   </body>
25   </html>

[b] Create the JavaScript File

In the public directory, create a main.js file with the following initial content:


1   document.getElementById('join-button').addEventListener('click', () => {
2       const room = document.getElementById('room-input').value;
3       if (room === "") {
4           alert("Please enter a room name.");
5           return;
6       }
7       document.getElementById('join-screen').style.display = 'none';
8       document.getElementById('conference-screen').style.display = 'block';
9       // Implement signaling and peer connection logic here
10   });


  • HTML Structure: The index.html file contains two main sections: the join screen and the conference screen. The join screen is displayed initially, and the conference screen appears after the user joins a room.
  • JavaScript Logic: The main.js file handles the user interaction for joining a room. It hides the join screen and displays the conference screen when the user clicks the join button.
By setting up the wireframe, you establish the basic structure of your Briefing WebRTC application. The next steps will focus on implementing specific features such as the join screen functionality, user controls, and rendering participant views.

Step 3: Implement Join Screen

Building the Join Screen

With the wireframe in place, the next step is to implement the functionality for the join screen. This involves setting up the client-side logic to join a conference room and establish a connection with the signaling server.

[a] Modify main.js to Include Signaling Logic

Enhance the main.js file to include the signaling logic using socket.io for real-time communication between clients.


1   const socket = io();
3   document.getElementById('join-button').addEventListener('click', () => {
4       const room = document.getElementById('room-input').value;
5       if (room === "") {
6           alert("Please enter a room name.");
7           return;
8       }
9       document.getElementById('join-screen').style.display = 'none';
10       document.getElementById('conference-screen').style.display = 'block';
12       socket.emit('join', room);
14       socket.on('new user', (userId) => {
15           console.log('New user connected:', userId);
16           // Initialize peer connection with the new user
17           initializePeerConnection(userId, true);
18       });
20       socket.on('signal', (data) => {
21           handleSignal(data);
22       });
23   });
25   function initializePeerConnection(userId, initiator) {
26       const peer = new SimplePeer({ initiator: initiator });
28       peer.on('signal', (signal) => {
29           socket.emit('signal', { signal: signal, to: userId });
30       });
32       peer.on('stream', (stream) => {
33           // Display the remote video stream
34           const remoteVideoContainer = document.getElementById('remote-video-container');
35           const videoElement = document.createElement('video');
36           videoElement.srcObject = stream;
37           videoElement.autoplay = true;
38           remoteVideoContainer.appendChild(videoElement);
39       });
41       // Handle incoming signals
42       peers[userId] = peer;
43   }
45   function handleSignal(data) {
46       if (peers[data.from]) {
47           peers[data.from].signal(data.signal);
48       }
49   }
51   const peers = {};

[b] Explanation

  • Socket Initialization: The socket variable is initialized to connect to the signaling server.
  • Join Room: When the join button is clicked, the client emits a join event to the server with the room name. It also sets up listeners for new user and signal events.
  • Initialize Peer Connection: The initializePeerConnection function sets up a new SimplePeer instance for each new user. It handles signaling and receiving remote video streams.
  • Handle Signal: The handleSignal function processes incoming signals from other peers.
With this implementation, your join screen now allows users to connect to a room and establish peer-to-peer connections using WebRTC. The next steps will involve adding user controls and rendering participant views to enhance the functionality and user experience of your application.

Step 4: Implement Controls

Adding User Controls

In this step, we will implement the user controls, such as the ability to mute/unmute audio, toggle video, and leave the conference. These controls are essential for a functional video conferencing application.

[a] Update HTML for Controls

Modify your index.html file to include buttons for muting, toggling video, and leaving the conference.


1   <div id="conference-screen" style="display:none;">
2       <h1>Conference Room</h1>
3       <div id="local-video-container"></div>
4       <div id="remote-video-container"></div>
5       <button id="mute-button">Mute</button>
6       <button id="video-button">Toggle Video</button>
7       <button id="leave-button">Leave</button>
8   </div>

[b] Add Control Logic in main.js

Update main.js to handle the user controls.


1   const localStream = new MediaStream();
2   const localVideo = document.createElement('video');
3   localVideo.srcObject = localStream;
4   localVideo.muted = true;
5   localVideo.autoplay = true;
6   document.getElementById('local-video-container').appendChild(localVideo);
8   navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(stream => {
9       stream.getTracks().forEach(track => localStream.addTrack(track));
10       for (let userId in peers) {
11           peers[userId].addStream(localStream);
12       }
13   });
15   document.getElementById('mute-button').addEventListener('click', () => {
16       const audioTrack = localStream.getAudioTracks()[0];
17       audioTrack.enabled = !audioTrack.enabled;
18       document.getElementById('mute-button').textContent = audioTrack.enabled ? 'Mute' : 'Unmute';
19   });
21   document.getElementById('video-button').addEventListener('click', () => {
22       const videoTrack = localStream.getVideoTracks()[0];
23       videoTrack.enabled = !videoTrack.enabled;
24       document.getElementById('video-button').textContent = videoTrack.enabled ? 'Disable Video' : 'Enable Video';
25   });
27   document.getElementById('leave-button').addEventListener('click', () => {
28       socket.emit('leave', room);
29       location.reload();
30   });
32   socket.on('user left', (userId) => {
33       if (peers[userId]) {
34           peers[userId].destroy();
35           delete peers[userId];
36       }
37   });

[c] Explanation

  • Local Stream Setup: Capture the user's media stream and add it to the local video element.
  • Mute Button: Toggle the audio track of the local stream.
  • Video Button: Toggle the video track of the local stream.
  • Leave Button: Emit a leave event to the server and reload the page to disconnect.
  • Handle User Leaving: Clean up peer connections when a user leaves.
With these user controls implemented, your Briefing WebRTC application now allows users to manage their audio and video streams and leave the conference when needed. The next step will focus on implementing the participant view to display video streams from other users.

Get Free 10,000 Minutes Every Months

No credit card required to start.

Step 5: Implement Participant View

Creating the Participant View

The participant view is essential for displaying video streams from other users in the conference. This step involves setting up the logic to manage and render these streams dynamically.

[a] Update HTML for Remote Video Container

Ensure that your index.html file has a dedicated section for displaying remote video streams.


1   <div id="conference-screen" style="display:none;">
2       <h1>Conference Room</h1>
3       <div id="local-video-container"></div>
4       <div id="remote-video-container"></div>
5       <button id="mute-button">Mute</button>
6       <button id="video-button">Toggle Video</button>
7       <button id="leave-button">Leave</button>
8   </div>

[b] Update JavaScript to Handle Remote Streams

Enhance main.js to manage incoming remote streams and render them in the participant view.


1   const socket = io();
3   document.getElementById('join-button').addEventListener('click', () => {
4       const room = document.getElementById('room-input').value;
5       if (room === "") {
6           alert("Please enter a room name.");
7           return;
8       }
9       document.getElementById('join-screen').style.display = 'none';
10       document.getElementById('conference-screen').style.display = 'block';
12       socket.emit('join', room);
14       socket.on('new user', (userId) => {
15           console.log('New user connected:', userId);
16           initializePeerConnection(userId, true);
17       });
19       socket.on('signal', (data) => {
20           handleSignal(data);
21       });
23       socket.on('user left', (userId) => {
24           if (peers[userId]) {
25               peers[userId].destroy();
26               delete peers[userId];
27           }
28           const videoElement = document.getElementById(userId);
29           if (videoElement) {
30               videoElement.remove();
31           }
32       });
33   });
35   function initializePeerConnection(userId, initiator) {
36       const peer = new SimplePeer({ initiator: initiator, stream: localStream });
38       peer.on('signal', (signal) => {
39           socket.emit('signal', { signal: signal, to: userId });
40       });
42       peer.on('stream', (stream) => {
43           // Display the remote video stream
44           const remoteVideoContainer = document.getElementById('remote-video-container');
45           const videoElement = document.createElement('video');
46           videoElement.id = userId;
47           videoElement.srcObject = stream;
48           videoElement.autoplay = true;
49           remoteVideoContainer.appendChild(videoElement);
50       });
52       peers[userId] = peer;
53   }
55   function handleSignal(data) {
56       if (peers[data.from]) {
57           peers[data.from].signal(data.signal);
58       }
59   }
61   const peers = {};
63   const localStream = new MediaStream();
64   const localVideo = document.createElement('video');
65   localVideo.srcObject = localStream;
66   localVideo.muted = true;
67   localVideo.autoplay = true;
68   document.getElementById('local-video-container').appendChild(localVideo);
70   navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(stream => {
71       stream.getTracks().forEach(track => localStream.addTrack(track));
72       for (let userId in peers) {
73           peers[userId].addStream(localStream);
74       }
75   });
77   document.getElementById('mute-button').addEventListener('click', () => {
78       const audioTrack = localStream.getAudioTracks()[0];
79       audioTrack.enabled = !audioTrack.enabled;
80       document.getElementById('mute-button').textContent = audioTrack.enabled ? 'Mute' : 'Unmute';
81   });
83   document.getElementById('video-button').addEventListener('click', () => {
84       const videoTrack = localStream.getVideoTracks()[0];
85       videoTrack.enabled = !videoTrack.enabled;
86       document.getElementById('video-button').textContent = videoTrack.enabled ? 'Disable Video' : 'Enable Video';
87   });
89   document.getElementById('leave-button').addEventListener('click', () => {
90       socket.emit('leave', room);
91       location.reload();
92   });

[c] Explanation

  • Remote Stream Handling: When a new user joins, the initializePeerConnection function sets up a new SimplePeer instance that listens for remote streams and displays them in the remote-video-container.
  • Clean Up on User Leave: When a user leaves, their video element is removed from the DOM to keep the interface clean.
  • Local Stream Management: The local video stream is initialized and displayed in the local-video-container.
With the participant view implemented, your Briefing WebRTC application can now display video streams from all participants. The final step will be running and testing your code to ensure everything works as expected.

Step 6: Run Your Code

Running and Testing the Application

With all the components in place, it's time to run and test your Briefing WebRTC application to ensure it functions correctly. Follow these steps to start the server and verify the application:

Start the Server

Open your terminal, navigate to the root directory of your project, and run the server using Node.JS.


1   node server/server.js
You should see a message indicating that the server is running on port 3000.

Open the Application in a Browser

Open your web browser and navigate to http://localhost:3000. You should see the join screen of your Briefing WebRTC application.

Test the Application

  • Join a Room: Enter a room name and click the join button. The conference screen should appear.
  • Check Video and Audio: Verify that your local video and audio streams are visible and functional.
  • Join from Multiple Browsers: Open the application in multiple browser tabs or different devices, join the same room, and ensure that the video streams from all participants are visible.
  • Test Controls: Use the mute, video toggle, and leave buttons to ensure they work as expected.


  • Common Issues: If you encounter any issues, check the browser console for error messages. Common problems may include permission issues with accessing the camera and microphone, or connectivity issues.
  • Debugging: Ensure that the signaling server is running correctly and that all peers are connected.
By following these steps, you can run and test your Briefing WebRTC application to ensure it meets your requirements and works smoothly.


In this guide, we covered the essential steps to create a Briefing WebRTC application. Starting from setting up the project and installing necessary dependencies, we moved through structuring the project, implementing the join screen, adding user controls, creating the participant view, and finally running and testing the application. By following these steps, you can build a functional and scalable WebRTC-based video conferencing application.

Want to level-up your learning? Subscribe now

Subscribe to our newsletter for more tech based insights