Build a One-to-One Chat App with JavaScript

More and more applications are seeing the value in allowing users to communicate in real-time, either with one another or with their support team. Adding this feature to existing applications, or even new ones, however, can seem like a giant, time-consuming undertaking. To help make this task seem less daunting, let me introduce Stream Chat; Stream Chat can help you implement a chat solution in your application in minutes!

In this tutorial, we'll walk through building a one-to-one user chat application using just the Stream Chat SDK and Vanilla JavaScript.

You can also get the source code for this tutorial on GitHub.

Prerequisites

To follow along with this tutorial, you'll need to have a basic understanding
of JavaScript.

You'll also want to make sure you have Node (version 8 or above) installed on your system.

To check if you have Node installed on your system, enter the command below in your terminal:

$ node -v

If Node is installed, you will see the version installed displayed in response to the above command; otherwise, you will receive output similar to “command not found: node”.

Also, we recommend that you install the nodemon package, which will automatically restart the node application when it detects file changes in your directory (no more reloading!):

$ npm install -g nodemon

Once you've confirmed you have the necessary tools installed, let’s dive in!

Creating a Stream Account

Let's create a Stream account so that we can use the Stream API. We can do this by navigating to the Stream website and clicking the SIGNUP button.

On the modal that pops up, fill in your USERNAME, EMAIL ADDRESS, and PASSWORD and click the CREATE FREE ACCOUNT button:

Creating a Free Stream Chat account

On your Stream Dashboard (where you'll be directed after creating an account), you'll find your APP ID, API KEY, and API SECRET, which we’ll use in a bit:

Account Dashboard

Take note of these keys, we will be using them in the next steps. Also, keep them safe and private.

Creating the Project

To begin creating our project, initiate the directory for it in the directory where you store your code, and name it stream-chat-javascript:

$ mkdir stream-chat-javascript

Inside of your new stream-chat-javascript directory, create the following directory and file:

  • public - this houses all our client-side files
  • server.js - contains our server-side code

Then, inside the public directory, create the following files:

  • custom.js
  • index.html
  • style.css

Next, let’s initialize NPM, so that we can install packages; open your terminal and cd into your project root directory (stream-chat-javascript), then run:

$ npm init

On the prompt that appears, press enter through all the prompts; the defaults for each will work for our application.

Creating a Node Server

Now, let’s install express and the Stream Chat server SDK:

$ npm install express stream-chat

Now that we have installed express let’s spin up a new Node server to serve our files; add the code below to the server.js file:

https://gist.github.com/nparsons08/23a84134a4e3639f73d9ec0b153fb8f7

Then, start up the server from your terminal by running this command:

$ nodemon server.js

Here, we have created a Node server that will be running on port 8800. You can now access the project on http://localhost:8800.

Generating and Utilizing Tokens

We’ll be using the JavaScript SDK on both the server, to generate our tokens, and the client end, to get real-time updates of what is happening on the chat, including real-time messages.

To be able to initialize the client, we need to get a valid token, which we can generate from our Node server. Add the below piece of code for generating tokens in the server.js file:

https://gist.github.com/nparsons08/2174410cb77b89b5e6712e8e0a1c51d6

Make sure to update the <STREAM_API_KEY> and <STREAM_API_SECRET> placeholders with the ones we grabbed above.

With the above code, we have created a new /token endpoint, to which we can make a request when generating a new token. We just need to pass in the username to the URL via the query string - http://localhost:8800/token?username=theUserUsername when we want to generate a token for a user.

Creating the Interface

Add the following code to your public/index.html file to create your chat interface:

https://gist.github.com/nparsons08/91feb2fefc716ba12f701b10168d261a

The three <script>s at the end of this code allow us to connect into Stream, make HTTP requests (using Axios), and connect into the actions for the page, from our custom.js file.

Styling the App

Let's get our styling started by inserting the following into style.css:

https://gist.github.com/nparsons08/d0ec6114ab3806e2e3c73e4eacf3ecb9

Initializing the JavaScript SDK

The first step for creating the client-side of the app is to initialize the Javascript SDK. Add the code below to your public/custom.js file:

https://gist.github.com/nparsons08/bc38635a3426348f2f753e8f1a04cbd5

Before we can start using the client SDK, we must first set the current user. Add the function below to the public/custom.js file to do that:

https://gist.github.com/nparsons08/f9a13c59bf25a9d0cc988732e4691a61

When you load the app, the first page that shows up displays a form to input a username before proceeding. Currently, it does not do anything when you hit enter. Let’s fix that!

Add the code below to the public/custom.js file, so we can listen to the input for when a user hits enter so we can display their message in the chat area:

https://gist.github.com/nparsons08/927add8f7565666a6cf209ed752ebee5

Once the user hits enter, we call the initializeClient() function to initialize the client.

Listing Users

If you open the app, and input a username, then hit enter, you may find that the app is almost empty but promising!:

Chat message area

To start to fill things out, let’s create a function that takes in an array of users, and then populates them to the DOM by targeting the div with id of users:

https://gist.github.com/nparsons08/62504f6312fbbe98d31b109de6e9ba45

In the above code, we added a click event to each user which calls the selectUserHandler function when a user is clicked.

Next, let’s create the selectUserHandler function. Add the following code to public/custom.js:

https://gist.github.com/nparsons08/641fd26400c1322a0be8285e11abba07

In this function, when we click on a user, we style that user differently so that we can uniquely identify the current user from other users.

Finally, let’s fetch and list users! Add the following function to the public/custom.js file:

https://gist.github.com/nparsons08/b1cea27f66f69447a3c606a377bdd034

Now call this function in the initializeClient function so that we can fetch users as soon as we initialize the chat:

https://gist.github.com/nparsons08/6f01751a819419fa147f489b9a3310f4

Initializing a Channel

To set up a channel for a one-to-one chat, we only need to pass in the two users' IDs and not worry about the channel name.

Add the below function to the public/custom.js file for initializing a channel:

https://gist.github.com/nparsons08/8fc7fa3d9f5321eaad791306266ffb28

Now, let’s call this function when we click on a user that we want to chat with. Add the below to the selectUserHandler function:

https://gist.github.com/nparsons08/db59a6bd315a9473cdfd3a5c24de2b54

Adding New Messages to the Channel

Now, let’s create a function to append messages to the DOM. Add the below function to the public/custom.js file:

https://gist.github.com/nparsons08/603821f8910470e1801f06d1713f7d9d

Note: This function will extract the user's username and message values from the payload, and then create a new DOM element that holds the username and message. Once created, the message will be appended to the DOM using the message ID.

Displaying Both Old and New Messages

By adding the code below to the initializeChannel(members) method, we can listen for new messages to the channel:

https://gist.github.com/nparsons08/700b9c5a952b0fd823ba6b6719b6fb17

We can add the following to the initializeChannel(members) function to render messages already in the channel:

https://gist.github.com/nparsons08/5ee2fbc700c74f8b6777174cfd2ec596

Exchanging Messages

We have covered receiving messages, let's now jump into how to handle sending messages. Add the below function to the public/custom.js file:

https://gist.github.com/nparsons08/2d55347ac0f2552bc2c9eed3e71ec129

Now that we have the framework set up, we can listen for the message-input and the pressing of the Enter key and add the message to the channel:

https://gist.github.com/nparsons08/afa2b19b4ab260ee802ee297289108db

Testing It Out

To test out the chat:

  1. Open the application in two different tabs or browsers.
  2. Type in a username and hit Enter, in each.
  3. Select the user on the other tabs.
  4. Exchange messages!

Wrapping Up

In this post, we walked through how to create a web app to allow two users to converse in real-time, using Stream Chat. This is just the basics of what is possible. Check out the Stream Chat SDK to learn about even more ways you can improve the form and function of your app!

We can't wait to see what you create! Thanks for reading and happy coding!

TutorialsChat