This tutorial is outdated. We're currently working on an updated version. In the meantime, for instructions on building a chat app using CometChat, please visit our documentation.
App and web development have come a long way over the last few years. We use a lot of chat/meeting apps every day. One of the most widely used features is live chat including text chat and voice chat such as WebEx, Zoom, Slack, Microsoft Teams, and so on. Using the React CometChat UI Kit, Firebase backend services, you will learn how to build the WebEx clone.
Follow along the steps to build a WebEx clone that will allow users:
1. Users
User authentication - sign up, log in, log out.
User invitations - custom links for virtual meetings that can be shared to invite participants
2. Virtual Conferencing
Create personal meeting rooms and invite participants via a link.
List online participants.
In-conference chat
Screen sharing.
Call recording
3. Login the logged-in user to CometChat
4. Create a user friendly and attractive UI
5. Add API call when a user registers so that the user is created in CometChat
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 webex-clone by running the following statement.
Step 3: You need to install some dependencies such as CometChat, Firebase, Validator, Uuid.
*Note: At this time of writing this tutorial, we are using the Firebase SDK with the version @8.9.1
Configuring CometChat SDK
Head to CometChat Dashboard and create an account.
Register a new CometChat account if you do not have one
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
From the dashboard, add a new app called "webex-clone".
Create a new CometChat app - Step 1
Create a new CometChat app - Step 2
Select this newly added app from the list.
Select your created app
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
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 the Groups tab and delete all the default groups (very important).
Navigate to Group tab and delete all the default groups
Create a file called **.env** in the root folder of your project.
Import and inject your secret keys in the **.env** file containing your CometChat and Firebase in this manner.
10. Make sure to include **.env** in your gitIgnore file from being exposed online.
Setting Up Firebase Project
According to the requirements of the WebEx clone, 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 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
Next, click the edit icon on the email/password provider and enable it.
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
Click on “Create Database"
Select location where you realtime database will be stored
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 “FIREBASE_REALTIME_DATABASE_URL” variable in your “Constants.java” file with that value.
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 date/time in milliseconds as you can see in the image below. Please do not forget the “.indexOn” for the “users” and “meetings”.
Firebase rules
On the Firebase dashboard, please click on the “Project Settings” to create the a new project and then create a new web project. After creating the web project successfully, you should see some Firebase credentials information as below.
Firebase credentials information
The above information will be stored in the .env file of the project so that we can use the Firebase services inside our application.
The below images demonstrate the data structure of the application. A user should have:
An avatar
An email
A full name
A unique id.
According to the requirements, each user should have a personal meeting room. For this reason, we have another property to contain the unique id of the personal meeting room for each user. It is the guid property.
On the other hand, we also have a data structure for meetings:
Guid - the meeting’s id.
Name - the meeting’s name.
Owner - the meeting’s owner’s id.
Firebase - Data Structure
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.
Configuring Images for the Application
In this project, we need to create a folder called “images” inside the root folder. The “images” folder is used to store all of the images that will be used to build the application. To get the images, you can refer to this link.
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 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.
isLoading: it is used to indicate that the loading indicator should be shown, or not.
user: it is used to store the authenticated information.
cometChat: it is used to store the CometChat instance.
id: it is used to store the menu id.
meeting: it is used to store the selected meeting.
hasNewMeeting: it is used to detect a new meeting has been created, or not. If its value is true, the application will reload the list of meetings to get the updated list.
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.
Actually, App.js does not contain only the above code. It also contains other business logic of the application. The full source code of App.js file 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 realtime 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.
Creating Common Service
We should follow the DRY principle in our code. DRY stands for “do not repeat yourself”. It means that we should not duplicate the business logic. To avoid duplication in our code, we need to create a file called “common.js”. This file will take responsibility for creating common services/functionalities in our application. Therefore, those functions could be shared and reused in different places. Please create the “services” folder inside the “src” folder, and then create the “common.js” file inside the “services” folder. The full source code of the “common.js” file can be found here.
According to the above code snippet, there are some methods that will be shared between different places in our application.
createCometChatGroup: It is used to create the CometChat group, a new CometChat group is created each time a new meeting is created. This function accepts three parameters - the comet-chat instance, the group’s id, and the group’s name.
showNotification: It is used to display the alert message in the application. For example, we need to show the success message after the user has created a new meeting. Or showing the error message if their user credentials are not correct when they are trying to log in to the application. This function accepts a single parameter - the message that we want to display.
insertFirebaseDatabase: It is used to insert Firebase the data into the Firebase Realtime Database service such as inserting a new meeting or new user information, and so on. This function accepts three parameters:
1. key: Meetings, users, …
2. id: Id of the created object such as the meeting’s id, the user’s id.
3. payload: The information of the created object such as the meeting’s information, the user’s information.
saveDataToLocalStorage: We need to store the authenticated information to the local storage. Apart from that, we also need to store the selected meeting in the local storage. Hence, the application can still retrieve the selected meeting even the users refresh the page. This function accepts two parameters - the key, and the payload.
navigate: It is used to navigate the end-users to different pages. This function accepts two parameters - the route that the end-users should be redirected to, and the callback function. The callback function is used to navigate the users to the corresponding routes.
Project Structure
The image below reveals the project structure. Make sure you see the folder arrangement before proceeding.
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. On other hand, it will be used to initialize CometChat. The full source code of the App.js file can be found here.
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
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 of 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 to the local storage for further usage such as getting that information in different places in the application, prevent the end-users come back to the login page after signing in to the application.
To login to the CometChat, we call the cometChat.login function, 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. Actually, 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-oder 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 withMeeting - Higher Order Component
We can start a meeting from different places in the application such as starting a meeting from the dashboard page, or the meetings page, and so on. After starting a meeting, we need to store the meeting information to the global state, the local storage because we would like to retrieve the previous state (the selected meeting) if the users refresh the page. Therefore, our application will not be crashed. Because this function needs to be used in different places, and we do not want to violate the DRY principle so we need to create a higher-order component to store the common methods. Hence, we can reuse those methods in different components by wrapping them in the higher-order component. Please create the “Meeting.js” file inside the “common” folder. The full source code can be found here.
As mentioned above, we create some common methods in the “common.js” file - saveDataToLocalStorage, navigate. Aside from that, we also use the setMeeting method from our React Context to set the selected meeting. All of these methods are used inside the saveAndJoinMeeting method, and that method will be passed to the WrapperComponent via props. Therefore, we have made our code reusable across different places in our app.
The Sign Up Component
The SignUp 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 cometChat.createUser function. 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:
Step 2: Copy the folder of the CometChat Pro React UI Kit you just cloned into the src folder of your project:
Add comet-chat-pro-react-ui-kit to src folder
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 is used to display the user’s avatar and the log out button. The full source code of the Header component can be found here.
The Logout Feature
The Logout Feature
After clicking the log out button, a confirm dialog will be displayed to ask the end-users whether they want to sign out from the application. To handle the logout process, the following steps will be executed:
Call the logout function of CometChat.
Remove the authenticated information from the global state, and the local storage.
Redirect the end-users to the log in page.
Please refer to the below code snippet for more information.
The Sidebar Component
The Sidebar Component
The Sidebar component is used to display the menu items for the application. In this application, we have two menu items - the dashboard, and the meetings. The dashboard page is used to show the person's meeting room and the introduction to the application. Aside from that, if the users click on the “Schedule” button on the dashboard page, or the “Meetings” item on the sidebar, the users will be redirected to the meetings page. On the meetings page, the users can see the list of their created meetings. On the other hand, they can create a new meeting, and join any meetings by using their ids. The full source code can be found here.
The Home Component
The Home Component
The Home page is used to show the person's meeting room and the introduction to the application. Aside from that, if the users click on the “Schedule” button on the dashboard page, or the “Meetings” item on the sidebar, the users will be redirected to the meetings page. The full source code can be found here.
According to the above code snippet, after clicking the “Start a Meeting” button, the “startMeeting” method will be executed. The following steps will have occurred:
Create a new CometChat group.
If the CometChat group was created, the application will save the selected meeting to the local storage, and the global state, and then redirect the users to the meeting page.
After the CometChat group was created, the application will save the selected meeting to the local storage, and the global state, and then redirect the users to the meeting page.
The ScheduleMeeting Component
The Schedule Meeting Component
The ScheduleMeeting component is a custom modal, it will be passed to the withModal - higher-order component. After the users click on the “Schedule a Meeting” button, that modal will have appeared. On that modal, the users can input the meeting’s name. After that, the users can click on the “Schedule a Meeting” button to create a new meeting. The following steps will have occurred:
Save new meeting to the Firebase Realtime Database service.
Create a new CometChat group.
The full source code can be found here.
The Join Meeting Component
The Join Meeting Component
According to the requirements, we can share the meeting’s ids with others. For this reason, other users can access the meetings by using their ids. The JoinMeeting component is a custom modal, it will be passed to the withModal - higher-order component. On the meeting page, the users click on the “Join a Meeting” button, the modal will have appeared, the users can input the meeting’s id and click on the “Join Meeting” button to join the meeting. The following steps will have occurred:
Joining a meeting means that the users will join the corresponding CometChat group. As mentioned in the previous section, whenever we create a new meeting, we will create a new CometChat Group.
Save the selected meeting in the local storage, the global state, and redirect the users to the meeting page.
The full source code can be found here.
The Meetings Component
The Meetings Component
The Meetings component is used to show the list of your created meetings. For example, Anna created three meetings. Hence, whenever Anna goes to the meetings page, the meetings component will display all of the meetings created by Anna. In this case, there are three meetings. On the other hand, the meetings page contains the “Schedule a Meeting” button, and the “Join a Meeting” button. We have talked about them in the previous sections. If the users click on the “Schedule a Meeting” button, the ScheduleMeeting component will be shown as a popup, and the users can use that component to create a new meeting. Aside from that, if the users click on the “Join a Meeting” button, the JoinMeeting component will be shown as a popup, and the users can use that component to join a new meeting by inputting the meeting’s id. The full source code of the Meeting component can be found here.
The Meeting Header Component
The Meeting Header Component
After click on the “Start a Meeting” button, the users will be redirected to the meeting page. On the meeting page, the MeetingHeader component is used to display the title of the meeting, and the back button, if the users click on the back button, the users will be redirected to the previous page. The full source code of the MeetingHeader component can be found here.
The Meeting Component
The Meeting Component
As mentioned above, after the users click on the “Start a Meeting” button on any item on the meetings list or the users join a meeting. The users will be redirected to the meeting page. The Meeting component will use CometChat SDK to start the direct call and the CometChatMessages component from the CometChat React UI Kit. Please create the “Meeting.js” file inside the “meeting” folder. The full source code can be found here.
We need to start a direct call after the users have been navigated to the Meeting page. We will the CometChat SDK to achieve that. For more information about that feature, you can refer to this link. The below code snippet also demonstrates how we achieve that in the WebEx clone.
Wrapping Up
In conclusion, we have done an amazing job in developing a WebEx clone by leveraging React.js, Firebase, CometChat SDK, and React UI Kit. You’ve been introduced to the chemistry behind WebEx and how the CometChat SDK makes the WebEx clone 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 and that you were able to successfully add mentions into your React chat app. Jump into the comments and let me know your experience.
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