How to Build a Livestream Chat App

Learn how to build a Livestream chat app using the CometChat React UI Kit and Firebase by following this step-by-step tutorial.

Hiep Le • May 2, 2022

App and web development have come a long way over the last few years. We use a lot of apps to live stream every day such as Facebook, Youtube, and so on. Using the React, React CometChat Extensions, React CometChat UI Kit, and Firebase backend services, you will learn how to build the Livestream chat app with minimal effort.

Follow along the steps to build the Livestream chat app that will allow users:

1. Users

  • User authentication - sign up, log in, log out.

2. Create Live Streams

  • The users can input some information to create a live stream such as the name, date, and description.

3. Join Live Streams

  • The users can view the list of current live streams on the home page and join any live streams that they want.

4. Live Streams

  • The users can view the current live stream.

  • The users can view the list of participants in the current live stream.

  • The users can chat with each other.

Some features will be applied and supported by using the CometChat extensions - message translation, sentiment analysis, profanity filter, emojis, stickers, and reactions.

Prerequisites

To follow this tutorial, you must have a degree of understanding of the general use of React.js. This will help you to improve your understanding of this tutorial.

Installing the App Dependencies

  • Step 1: You need to have Node.js installed on your machine

  • Step 2: Create a new project with the name livestream-app by running the following statement.

    npx create-react-app livestream

  • Step 3: You need to install some dependencies. Please get the list of dependencies from here, and then run.

    npm install

*Note: At this time of writing this tutorial, we are using the Firebase SDK with the version @8.9.1

Configuring CometChat SDK

  1. Head to CometChat Dashboard and create an account.

Register a new CometChat account if you do not have one

Register a new CometChat account if you do not have one

  1. After registering a new account, you need to the log in to the CometChat dashboard.

Log in to the CometChat Dashboard with your created account

Log in to the CometChat Dashboard with your created account

  1. From the dashboard, add a new app called livestream-app.

Create a new CometChat app - Step 1

Create a new CometChat app - Step 1

Create a new CometChat app - Step 2

Create a new CometChat app - Step 2

  1. Select this newly added app from the list.

Select your created app

Select your created app

  1. From the Quick Start copy the APP_ID, REGION, and AUTH_KEY, which will be used later.

Copy the the APP_ID, REGION, and AUTH_KEY

Copy the the APP_ID, REGION, and AUTH_KEY

  1. Navigate to the Users tab, and delete all the default users (very important).

Navigate to Users tab and delete all the default users

Navigate to Users tab and delete all the default users

  1. Navigate to the Groups tab and delete all the default groups (very important).

Navigate to Group tab and delete all the default groups

Navigate to Group tab and delete all the default groups

  1. Create a file called **.env** in the root folder of your project.

  2. Import and inject your secret keys in the **.env** file containing your CometChat and Firebase in this manner.

    REACT_APP_FIREBASE_API_KEY=xxx - xxx - xxx - xxx - xxx - xxx - xxx - xxx
    REACT_APP_FIREBASE_AUTH_DOMAIN=xxx - xxx - xxx - xxx - xxx - xxx - xxx - xxx
    REACT_APP_FIREBASE_DATABASE_URL=xxx - xxx - xxx - xxx - xxx - xxx - xxx - xxx
    REACT_APP_FIREBASE_STORAGE_BUCKET=xxx - xxx - xxx - xxx - xxx - xxx - xxx - xxx
    
    REACT_APP_COMETCHAT_APP_ID=xxx - xxx - xxx - xxx - xxx - xxx - xxx - xxx
    REACT_APP_COMETCHAT_REGION=xxx - xxx - xxx - xxx - xxx - xxx - xxx - xxx
    REACT_APP_COMETCHAT_AUTH_KEY=xxx - xxx - xxx - xxx - xxx - xxx - xxx - xxx

  3. Make sure to include **.env** in your .gitignore file from being exposed online.

Setting Up Firebase Project

According to the requirements of the Livestream chat app, you need to let users create a new account and login to the application, Firebase will be used to achieve that. Head to Firebase to create a new project and activate the email and password authentication service. This is how you do it:

To begin using Firebase, you’ll need a Gmail account. Head over to Firebase and create a new project.

Firebase

Firebase

Firebase provides support for authentication using different providers. For example, Social Auth, phone numbers, as well as the standard email and password method. Since you will be using the email and password authentication method in this tutorial, you need to enable this method for the project you created in Firebase, as it is by default disabled.

Under the authentication tab for your project, click the sign-in method and you should see a list of providers currently supported by Firebase.

Firebase Authentication

Firebase Authentication

Next, click the edit icon on the email/password provider and enable it.

Enable Firebase Authentication with Email and Password

Enable Firebase Authentication with Email and Password

Now, you need to go enable Firebase Realtime Database. We will Firebase Realtime Database to store the information of the users in the application. Please refer to the following part for more information.

Choose “Realtime Database” option

Choose “Realtime Database” option

Click on “Create Database

Click on “Create Database"

Select location where you realtime database will be stored

Select location where you realtime database will be stored

 Select “Start in test mode” for the learning purpose

Select “Start in test mode” for the learning purpose

Please follow the guidance from Firebase. After following all steps, you will see the database URL. If you just need to update the “REACT_APP_FIREBASE_DATABASE_URL” variable in your .env file with that value.

Database Url

Database Url.

On the other hand, your Firebase real-time database will be expired in the future. To update the rules you just need to select the “Rules” tab and update the read/write as you can see from the image below. Please do not forget to set the .indexOn for the “users” because we need to get the user’s information by email. Therefore, we need to make the query successful.

Database rules

Database rules

In this project, we also need to upload the product’s image. Therefore, we have to enable the Firebase Storage service, the Firebase Storage service helps us store the assets files including images, videos and so on. To enable the Firebase Storage service, please follow the below steps:

Enable Firebase Storage Service

Enable Firebase Storage Service

Click on the “Next” button

Click on the “Next” button

Click on the “Done” button

Click on the “Done” button

Update the rules

Update the rules

For the learning purposes, we need to update the rules of the Firebase Storage service. It means that everyone, who can access to the application, can upload to the Firebase storage.

Now, you need to go and register your application under your Firebase project. On the project’s overview page, select the add app option and pick web as the platform. After finishing this step, you should see your Firebase credentials as follow, please update your .env file with your Firebase credentials.

Firebase credentials

Firebase credentials

Firebase Dashboard

Firebase Dashboard

Once you’re done registering the application, you’ll be presented with a screen containing your application credentials.

 Data Structure - User

Data Structure - User

The above image describes the data structure of the users. A user will contain the following information:

  • About: The user’s description.

  • Email: The user’s email.

  • Fullname: The user’s full name.

  • id: The user’s id.

  • Image: The user’s image.

In this application, the end-users can create live streams. For this reason, we need to store the created live streams in the Firebase Realtime Database. The below image describes the data structure of the live streams.

Data Structure - Live Streams

Data Structure - Live Streams

  • CreatedBy: The information of the user who created the live stream.

  • Date: The live stream date.

  • Description: The live stream description.

  • id: The live stream id.

  • Name: The live stream name.

Configuring Styling for the Application

Inside your project structure, open the index.css files and paste the codes here. index.css file will contain all CSS of the application.

Creating React Context

In this application, we need to pass some data between the components. We can have several options to achieve that such as using state management libraries, RxJS, and so on. However, we can get in-built support from React by using the React Context API. the React Context API helps us pass data through the component tree without passing it down at every level. Please create the context.js file inside the src folder. The full source code of the context.js file can be found here.

Initializing CometChat for the Application

The below codes initialize CometChat in your app before it spins up. The App.js file uses your CometChat API Credentials. We will get CometChat API Credentials from the .env file. Please do not share your secret keys on GitHub. The App.js file will do other tasks, not just initializing CometChat. The source code can be found here.

Configuring the Firebase File

You need to create a firebase.js file inside the src folder and you need to enable Firebase real-time database. This file is responsible for interfacing with Firebase authentication and database services. Also, it makes ready our email/password authentication service provider enabling us to sign in with google. Secret keys will be stored in the .env file. As mentioned above, please do not share your secret keys on GitHub. Please create the firebase.js file inside the src folder. The full source code can be found here.

Creating Services

We should follow the DRY principle in our code. DRY stands for “don’t repeat yourself”. It means that we should not duplicate the business logic. To avoid duplication in our code, we need to create some service files. Each file contains some methods that will be used to handle an individual aspect in our application, for example, sending a notification, creating CometChat friends, inserting the data to the Firebase Realtime Database service, and so on. Please create the services folder inside the src folder. Inside the services folder, please create the below files. For the content of each file, you can find here.

  • cometchat.js: this file contains some functions that will be used to interact with the CometChat services such as creating a new CometChat friend, creating a new account, and so on. Please create the cometchat.js file inside the services folder. The full source code can be found here.

  • firebase.js: this file contains some functions that will be used to interact with the Firebase services. Please create the firebase.js file inside the services folder. The full source code can be found here.

    import { auth, realTimeDb, storage } from "../firebase";
    
    export const insert = async ({ key, id, payload }) => {
      await realTimeDb.ref(`${key}/${id}`).set(payload);
    };
    
    export const createAccount = async (email, password) =>
      await auth.createUserWithEmailAndPassword(email, password);
    
    export const login = async (email, password) =>
      await auth.signInWithEmailAndPassword(email, password);
    
    export const getSingleDataWithQuery = async ({ key, query, criteria }) => {
      if (!criteria) return;
      const snapshot = await realTimeDb
        .ref()
        .child(key)
        .orderByChild(query)
        .equalTo(criteria)
        .get();
      const val = snapshot.val();
      if (val) {
        const keys = Object.keys(val);
        return val[keys[0]];
      }
      return null;
    };
    
    export const getData = async (key) => {
      const snapshot = await realTimeDb.ref().child(key).get();
      const val = snapshot.val();
      if (val) {
        const keys = Object.keys(val);
        return keys.map((key) => val[key]);
      }
      return null;
    };
    
    export const upload = async ({ key, id, payload, entity, callback }) => {
      const uploadTask = storage.ref(`${key}/${id}`).putString(payload, "data_url");
      uploadTask.on(
        "state_changed",
        null,
        (error) => {},
        () => {
          storage
            .ref(key)
            .child(id)
            .getDownloadURL()
            .then((url) => {
              callback(entity, url);
            });
        }
      );
    };
    
    export const getRef = (child) => realTimeDb.ref().child(child);
    
    export const getDataRealtime = (ref, callback) => {
      ref.current.on("value", function (snapshot) {
        callback(snapshot.val());
      });
    };
    
    export const getDataRealtimeQuery = ({ ref, query, criteria, callback }) => {
      ref.current
        .orderByChild(query)
        .equalTo(criteria)
        .on("value", function (snapshot) {
          callback(snapshot.val());
        });
    };
    
    export const offRealtimeDatabase = (ref) => {
      ref.off("value");
    };‍

  • ui.js: this file contains some functions that are related to the UI such as showing/hiding the loading indicator. We need to show the loading indicator when performing the side effects and doing some asynchronous tasks so that we can improve the UX. Please create the “ui.js” file inside the “services” folder. The full source code can be found here.

    export const alert = message => {
      window.alert(message);
    };
    
    export const showLoading = () => {
      const loading = document.getElementById("loading");
      loading.classList.remove("hidden");
      loading.classList.add('shown');
    };
    
    export const hideLoading = () => {
      const loading = document.getElementById("loading");
      loading.classList.remove("shown");
      loading.classList.add("hidden");
    };

Project Structure

The image below reveals the project structure. Make sure you see the folder arrangement before proceeding.

Project Structure

Project Structure

Now, let's make the rest of the project components as seen in the image above.

The App.js File

The App.js file is responsible for rendering different components by the given routes. For example, it will render the login page if the user has not logged in, yet or it renders the home page if the user has signed in to the system. The full source code of the App.js file can be found here.

*Note: we need to create some components with empty content to make sure that the application will not throw any errors now. To know about the list of components that need to be created inside the components folder, we can refer to this link. Please remember that we just need to create empty components, we do not need to copy the content from the above link, the above link just can be used to know about the names of some components that need to be created. We will talk about these components later.

The Loading Component

The Loading Component

The Loading Component

The loading component will be shown when the system performs some side effects such as interacting with Firebase or calling CometChat APIs, and so on. This component will be used to increase user experience. If we do not have this component, the end-users cannot know when the data is loaded successfully. Please create the components folder inside the src folder, and create the common folder inside it. The common folder is used to store the common components that will be used in different places in your application. After that, you need to create the Loading.js file inside the common folder. The full source code of the loading component can be found here.

The Login Component

The Login Component

The Login Component

This component is responsible for authenticating our users using the Firebase authentication service. It accepts the user credentials and either signs him up or in, depending on if he is new to our application. See the code below and observe how our app interacts with Firebase and the CometChat SDK. Please create the login folder inside the components folder, and create the Login.js file inside the login folder. The full source code can be found here.

The above code indicates that we are using withModal as a higher-order component. This higher-order component will be used to reuse the code for showing and hiding the custom modal. In this case, we want to show the sign-up modal to let end-users register new accounts. We will discuss the sign-up component in the following section.

We store the authenticated Information in the local storage for further usage such as getting that information in different places in the application, preventing the end-users come back to the login page after signing in to the application.

To login to the CometChat, we call the login function from the cometchat.js file, you can refer to the below code snippet for more information.

The withModal - Higher-Order Component

As mentioned above, we would like to show the SignUp component as a modal. We have multiple modals in the application, and we should avoid duplicating common functionalities such as showing/hiding the modals, and so on. To reuse the common logic, we can have several options. In this project, we will create a higher-order component called withModal. That higher-order component helps us to avoid duplicating code and we can customize the UI for the modals. Please follow the below code snippet for more information. Please create the Modal.js file inside the common folder. The full source code can be found here.

The Sign Up Component

The Sign Up Component

The Sign Up Component

The sign-up component will help end-users to register new accounts. This component will do two things. The first thing is to register new accounts on Firebase by using the Firebase authentication service. Aside from that, it also registers new accounts on CometChat by using the CometChat SDK. Please create the register folder inside the components folder, and create the SignUp.js file inside it. The full source code can be found here.

To create a new CometChat account, we call the createAccount function from the cometchat.js file. You can refer to the below code snippet below for more information.

Add the CometChat UI to Our Application

Before we can use the CometChat Pro React UI kit, we need to add it in our project so that we can reference it. In this case, we are using React UI Kit v3.0. To do that, follow the next steps:

  • Step 1: Clone the CometChat React UI Kit Repository like so:

    git clone https://github.com/cometchat-pro/cometchat-pro-react-ui-kit.git

  • Step 2: Copy the folder of the CometChat Pro React UI Kit you just cloned into the src folder of your project:

Project Structure

Project Structure

React UI Kit Dependencies

React UI Kit Dependencies

  • Step 3: Copy all the dependencies from the package.json file of the CometChat Pro React UI Kit folder and paste them in the dependencies section of the package.json file of your project.

  • Step 4: Save the file and install the dependencies like so: npm install

As soon as the installation is completed, you now have access to all the React UI Components. The React UI kit contains different chat UI components for different purposes as you can see in the documentation here. It includes:

1. CometChatUI

2. CometChatUserListWithMessages

3. CometChatGroupListWithMessages

4. CometChatConversationListWithMessages

5. CometChatMessages

6. CometChatUserList

7. CometChatGroupList

8. CometChatConversationList

The Private Route Component

We need to have some private routes in our application. It means that the end-users cannot access those routes if they have not logged in to the application. To achieve that, we need to create the PrivateRoute component. The PrivateRoute component will check the authenticated information in the local storage, if the information is existing in the local storage, the users can access the private routes and vice versa. Please create the PrivateRoute.js file inside the common folder. The full source code can be found here.

The Header Component

The Header Component

The Header Component

After the users log in to the application, the Header component will be used to show the app’s name, the greeting, and some menu options. There are some menu options on the Header component, they are Home, Create LiveStream, and Logout. To create a new live stream, the users can click on the Create LiveStream option, they will be redirected to the Create LiveStream page. If the users want to go back to the home page, they can click on the Home option. The last but not least, to log out from the application, the users can click on the Logout option. After clicking on that option, a confirmation dialog will be shown and the users can log out by clicking on the Ok button, we will talk about these pages/features in the upcoming sections. The full source code of the Header component can be found here.

The Logout Feature

The Logout Feature

The Logout Feature

To log out from the application, the users need to click on the Logout option on the Header component, after the users click on that option, a confirmation dialog will be shown as we can see from the above image. If the users click on the Ok button, the following things will happen.

  • We will log out from the CometChat platform by calling cometChat.logout(); (cometChat will be the cometChat instance that we get from the created React context).

  • We will remove the authentication information from the global state (user state in the React context) and the local storage.

  • We will redirect the users to the login page.

You can refer to the below code snippet for more information.

The Create LiveStream Component

The Create LiveStream Component

The Create LiveStream Component

To create a live stream in our application, the users need to go to this page by clicking on the Create LiveStream option on the Header component. On this page, we will show the page title, three input elements - live stream name, live stream data and live stream description, and the submit button. All of the fields are required. To create a new live stream:

  • The users need to input all of the required information

  • Click on the submit button.

  • The application will get the input information. In this case, we attach each input element with a ref to avoid extra re-rendering whenever the users input on those elements.

  • The application will validate the input information.

  • If the input information is valid, the request payload will be built and sent to the Firebase real-time database services. When we create a live stream. It means that we also create a CometChat group because we will use the CometChat services to achieve the chat and live stream features. Therefore, we will call cometChatService.createGroup() function.

  • If the input information is not valid, the corresponding alert will be shown to inform the users.

Please create the create-livestream folder inside the components folder, and then create the CreateLiveStream.js file inside it. The full source code can be found here.

To create a CometChat group, we can refer to the below code snippet and link.

The Home Component

The Home Component

The Home Component

The Home component will show the list of all created live streams in our application. Therefore, other users can join any live streams by clicking on the Join button. Please create the home folder inside the components folder, and then create the Home.js file inside the home folder. To develop the Home component, we have the following steps:

  • Define a state which is called livestream.

  • Define a Firebase ref by using useRef hook - livestreamsRef. To get a Firebase live streams ref, we call firebaseService.getRef("livestreams").

  • Define a function which is call loadLivestreams. Inside that function, we will use firebaseService.getDataRealtime(livestreamsRef, onDataLoaded);. We pass the livestreamsRef that we created at the above step. Following that, we also pass a function (onDataLoaded) as a callback function. It means that after getting the response from the Firebase services, the onDataLoaded will be executed to update the corresponding state.

  • Define an useEffect to call the loadLivestreams function when the component has been bootstrapped.

  • As we can see from the above image, we also have the join button. Hence, we need to handle the event when the users click on the join button. We define the joinLivestream function and associate that function to onClick the join button.

  • As mentioned above, we will use the CometChat services to achieve the chat, live stream feature. In terms of CometChat, each live stream will correspond to a CometChat group. It means that whenever the users join a live stream, they also join a CometChat group implicitly. To achieve that, we call the cometChatService.joinGroup() function.

  • Inside the joinLivestream function, we also call the setUpLivestream function. The setUpLivestream function will be used to save the selected live stream to the local storage. for this reason, when we go to the LiveStream detail component (we will talk about it later) we can retrieve the selected live stream information from the local storage. On the other hand, the setUpLivestream function will redirect the users to the LiveStream detail component.

The full source code can be found here.

To join a CometChat group, you can refer to the below code snippet and this link.

The Live Stream Header Component

s efdccccafdbacccdface screenbshotb batb bam

The Live Stream Header Component

The LiveStreamHeader component is used to show the selected live stream information. On the other hand, we can click on the left-arrow icon to leave the current live stream. Please create the livestream-header component inside the components folder, and then create the LiveStreamHeader.js file inside the livestream-header folder. To develop the LiveStreamHeader component, we need to follow the below steps:

  • We need to define a livestream prop. It means that the selected live stream will be passed to the LiveStreamHeader component via props. After that, we can show the selected live stream information.

  • Define the stopLivestream function. Inside that function, we just redirect the users to the home page by calling history.push(“/”);

The full source code can be found here.

The Live Stream Detail Component

The Live Stream Detail Component

The Live Stream Detail Component

The live stream detail component is used to show the current live stream and the users can chat with others. You can see that it is so easy to achieve these complex features by using the CometChat services because the CometChat services handle everything behind the scenes for us.

Please create the livestream-detail folder inside the components folder, and create the LiveStreamDetail.js file inside it. To develop this component, we can follow the below steps.

  • Define a state which is called livestream.

  • Get the cometChat instance from the created React context.

  • Define the history object by using the useHistory hook from the react-router-dom library because we need to redirect the users the home page if they want to live the current live stream.

  • Define an useEffect to get the selected live stream from the local storage whenever the component has been bootstrapped. After that, we will update the livestream state.

  • Define another useEffect, and that useEffect just can run whenever we make sure that the livestream state and the cometChat instance exist. We will call a function which is called startDirectCall. Inside the startDirectCall function, we will use the CometChat service to start a direct calling.

  • To achieve the chat feature, we need to import { CometChatMessages } from "../../cometchat-pro-react-ui-kit/CometChatWorkspace/src"; and then use the CometChatMessages component inside the LiveStreamDetail component. Therefore, we can see that, we do not need to do anything related to calling or chat features because the CometChat services handle everything for us.

  • As mentioned above, each live stream corresponds to a CometChat group. Hence, we need to pass a prop to the CometChatMessages component as follows - <CometChatMessages chatWithGroup={livestream.id} /> (livestream.id is the CometChat group’s id).

The full source code can be found here.

To start a direct call in CometChat, you can refer to the below code this snippet and this link.

Enable CometChat Extensions

We can see that we can achieve the live stream and chat features so easily, we do not need to do any complex tasks, we just need to import and use the CometChat services/components and the CometChat team will handle everything for us.

On the other hand, when we talk about chat feature, it is not really about a simple chat feature. We need to achieve the following things.

  • Message translation.

  • Sentiment analysis.

  • Profanity filter.

  • Emojis.

  • Stickers.

  • Reactions.

The question is that how we can achieve the above features, if we want to do the above features, it would take a lot of time, we have to investigate a lot of things, and take care of both front-end and back-end development. Fortunately, by using the CometChat extensions we can have these features so easily with just a few clicks. Please follow the below steps:

  • Step 1: Go to the CometChat dashboard and click on the Extensions option.

Go to the CometChat dashboard and click on the Extensions option

Go to the CometChat dashboard and click on the Extensions option

  • Step 2: We will be redirected to the Extensions page, we need to scroll down a bit and find the below extensions.

  • Message translation.

  • Sentiment analysis.

  • Profanity filter.

  • Emojis.

  • Stickers.

  • Reactions.

  • Step 3: We need to click on the toggle buttons to turn on/off any extensions that we want.

Click on the toggle buttons to turn on/off any extensions that we want

Click on the toggle buttons to turn on/off any extensions that we want

That’s all. After we enable those extensions, the CometChat UI Kit will handle everything for us. That’s great, right?

In fact, we are using Javascript to build the livestream app. However, with supports from the CometChat services, we can build the livestream app with famous technologies in the world such as React, Angular, Vue, React Native, IOS Swift, Android (Java/Kotlin), Ionic, Flutter. You can refer to the CometChat documentation for more information.

Wrapping Up

In conclusion, we have done an amazing job in developing a Livestream chat app by leveraging React.js, Firebase, CometChat Extensions, CometChat SDK, and React UI Kit. You’ve been introduced to the chemistry behind the Livestream chat app and how the CometChat services make the Livestream chat app buildable.

You have seen how to build most of the chat functionalities such as real-time messaging using CometChat. I hope you enjoyed this tutorial.

About the Author

Hiep Le is a software engineer. He takes a huge interest in building software products and is a full-time software engineer. Most of his work is focused on one thing - to help people learn.

Hiep Le

CometChat

Hiep Le is a software engineer. He takes a huge interest in building software products and is a full-time software engineer. Most of his work is focused on one thing - to help people learn.

Share it with everyone!

Try out CometChat in action

Experience CometChat's messaging with this interactive demo built with CometChat's UI kits and SDKs.