Add Texting Functionality to a Video Chat With Vonage Video API

Published April 21, 2020 by Hui Jing Chen

This series of tutorials will explore the Vonage Video API (formerly TokBox OpenTok) and what you can build with it. The Video API is very robust and highly customizable, and in each post we’ll show how to implement a specific feature using the API. This time we will look at how to add texting to a basic audio-video chat.

As this application will require some server-side code, we will use Glitch for ease of setup. You can also download the code from this Glitch project and deploy it on your own server or hosting platform of choice (may probably require some configuration tweaking based on the requirements of your platform).

We will not be using any front-end frameworks for this series, just vanilla Javascript to keep the focus on the Video API itself. At the end of this tutorial, you should be able to have an audio-video chat application with text chat functionality. Text chat is implemented using the signaling API.

Screenshot of video chat with text chat

The final code for this application can be found in this GitHub repository or remixed on Glitch.


Before we get started, you will need a Vonage Video API account, which you can create for free here. You will also need Node.js installed (if you are not using Glitch).

This tutorial builds on the first introductory post in the series: Building a Basic Video Chat. If this is your first time using the Video API, we highly suggest you go through that because it covers the following basic setup:

  • Create a Vonage Video API project
  • Setting up on Glitch
  • Basic project structure
  • Initializing a session
  • Connecting to the session, subscribing and publishing
  • Basic layout styles for a video chat

Basics of Text Chat With Vonage Video API

Implementing text chat with the Video API is done via the signaling API. This signalling mechanism allows clients connected to a session to send text and data to each other. We will only focus on text for now.

The Video API Client SDK will dispatch an event when the client receives a signal. For a basic text chat where messages are visible to all connected clients, we will use the signal() method of the Session object. Participating clients will receive that signal by listening to the signal event dispatched by the Session object.

For an in-depth look at what is accessible via the Session object, its properties, methods and events, please refer to SDK reference for the Session object.

Initial Setup

As we are building onto a basic video chat, start off by remixing the project for the basic video chat built in the previous tutorial. Click the big Remix button below to do that. 👇

remix this

Your folder structure should resemble something like this:

Folder structure of the project

As mentioned at the start, TokBox OpenTok is now Vonage Video API. We haven’t made any changes to our package names, so you will still reference OpenTok in your code.

If you had remixed the Glitch project, your server.js file should already look like this:

To get the video chat up and running, go to the .env file and fill in your API key and secret for your project, which you can find from the dashboard. Once that’s done, we will be working on the client-side code to get the text chat working before revisiting the server.js file again.

Add the Required Markup

Our application will be made up of 2 pages. A landing page with two text inputs. One for users to create a session, which we will call a “Room” so subsequent participants can join that same “Room”. The other text input is for users to enter a display name they can use to identify themselves.

The page will have a simple form element with two input fields for users to submit their room name and user name. Let’s add the user name field to the form.

We also need to add a chatbox to the index.html page. Let’s add the markup for a chat window with a header, an area to display messages, and an input at the bottom to type and send messages. To maximise screen space, the chat window will be off-screen by default and only triggered when you click the chat button at the bottom right corner of the page.

Chat button to trigger chat window

Add the following markup to your page, we will add the styles to make the button look like the above design in the next section.

We also want to add the markup for the chat window to the index.html file.

Bare bones chat window which will slide in from the right

Style the Chat-Related Elements

Our chat interface will be hidden away from view until needed, since the main feature of this application is the video chat. To toggle the chat interface, users will click the chat button on the bottom right corner of the page. This button has an SVG icon to indicate it triggers the chat.

We are using CSS to transform the chat window outside the viewport by default. When someone clicks on the chat icon, it will toggle a CSS class that changes the translateX value such that the window slides into view from the right side of the screen.

Let’s add some styles for the header, messages area and message input form as well.

With these styles, you should be able to see a chat icon in the bottom-right corner of the index.html file after you have entered the room. But clicking on it does not do anything yet.

Let’s add an event handler to toggle a CSS class to slide the chat window into view in the client.js file. As well as one on the close icon of the chat window to slide it back out.

This is not the only way to style a chat interface, so feel free to change things up to suit your needs.

Using the Signal API for Text Chat

Let’s make a few more tweaks to the base project and get the most basic text chat working.

We’ll move the session variable out of the initializeSession function and declare it globally at the top of the client.js file.

Add an event listener to the chat form, which will send a signal to all clients connected to the Session when the form is submitted.

We also need another event listener to receive that message by listening to the signal event dispatched by the Session object. The data payload from that event will be used to print the message into the message area of the chat window.

This is the basic mechanism of text chat with the Video API. If you type something in the chat window and submit, it should display on the screen.

Identify Participants in the Chat

However, to make the chat more user-friendly, we also want to add a means of identifying who said what in the chat. We will make use of the user name input on the landing page to get that information, passing it on to the server as a query string in the URL.

The following script on the landing.html page passes the room name and user name entered to the index.html page.

When the index.html page loads, it will trigger a POST request to the session/:name route, extracting the submitted user name from the URL and passing it onto the server.

Now we will need to modify that route in the server.js file so it will handle the room name and user name and return the required information for the initializeSession function. We also need to include a middleware to handle the request payload.

On the client.js, we can now display the user name for the participant who typed the message by modifying the data property of the session.signal() method.

Now when you submit a text message, it will be prepended with the user name you used when you entered the room.

Set up PouchDB as a Data Store

If you refresh the page, however, all previous chat messages are gone. This is because we have not stored the messages but merely displayed them on the screen. Let’s introduce some sort of data store for the messages.

We’ll be using PouchDB on the server in this tutorial, but you are free to replace this with any data store of your choice.

Install pouchdb-node with the following command (note that using pnpm is a Glitch thing):

pouchdb-node installation on Glitch

Let’s check that things are running as expected.

You should see the following in the Glitch logs.

Database information printed to console

PouchDB provides a fully asynchronous API, although it also includes the option for users to choose between the callback format or the promise format. We will be using the promise format for this tutorial, and the code will reflect as such.

Instead of storing session information in an object variable, we will store it in our new database. Remove the following line from the server.js file.

Let’s make more tweaks to the /session/:name route. We first check the database to verify if a session exists, if it does, we retrieve the associated information and generate the token from it. If the session does not exist, we will create a new session, store it in the database, then generate the token accordingly.

Add Stream Names to the UI

We can make use of the stream name in the response to label streams so participants can hover over each participant’s video stream to see a name. Both the initPublisher() method and the subscribe() method accepts an optional properties argument, which allows us to pass in customisation options for the stream.

Hover over a video stream to see the stream name

Save Messages Into the Database

When participants send text messages, we want to POST them to the server to be stored in the database. Let’s create a saveMessage() function to do that.

Modify the event listener on the chat form to trigger this function whenever a participant submits a text message.

On the server.js file, we need to add a handler for this POST request as well.

Now that our messages are being stored, we want to display them whenever the page loads. We will add a getChatHistory() function on the client-side which triggers a GET request to retrieve all the stored messages for that session and display them in the chat window.

And the corresponding route on the server side to pass the messages as an array back over to the client.

So now even if you refresh the page while the session is still going on, the messages will still be there. Also, if you enter the same room name as a previous session with stored chat history, that chat history will be displayed.

What’s Next?

The final code on Glitch and GitHub contains everything we covered in this fairly lengthy post but re-organised so the code is cleaner and more maintainable. Feel free to remix or clone the code and play around with it yourself.

There are additional functionalities we can build with the Vonage Video API which will be covered in future tutorials, but in the meantime, you can find out more at our comprehensive documentation site. If you run into any issues or have questions, reach out to us on our Community Slack. Thanks for reading!

Leave a Reply

Your email address will not be published.

Get the latest posts from Nexmo’s next-generation communications blog delivered to your inbox.

By signing up to our communications blog, you accept our privacy policy , which sets out how we use your data and the rights you have in respect of your data. You can opt out of receiving our updates by clicking the unsubscribe link in the email or by emailing us at