February 14, 2021

Building a Whatsapp Web clone with React , Express and Firebase - Part 1

We all love to chat , and you can’t name popular chatting apps without Whatsapp being in the list with 2 billion active monthly users as of March 2020 . In this 4 part tutorial series , we will build a web version of whatsapp and give you a way to create similar real-world projects using the same logic such as Facebook wall and more .

Before we begin , see below to have an idea of what we will be building ; -

Whatsapp web clone demo

As you can see , i could not afford to implement QR Scanning and since the users will only be web , then Phone Authentication method came in mind, specificaly Firebase authentication .

Apart from Firebase , we will be using React + Context API for state management on the frontend , Nodejs / Expressjs + MongoDB on the backend as well as Pusher to give us real-time messaging capabilities .

Okay , let’s get going . Make sure you have node installed , navigate to the directory where your project will reside and create project folder called whatsapp-web-clone.

Because we love frontend that much and want to see things happening , we are going to start with the client side , so inside your newly created project directory , create a client side react app by running below command

npx create-react-app client

Once the above has finished running , navigate to newly created client directory and run the below command to start our app

npm start

Let’s the work begin , since the user will require authentication , we are going to start with login page . Delete everything in App.css and change app.js file to below : -

import "./App.css";

function App() {
  return (
    <div className="App">
      <h1>Login Page</h1>
    </div>
  );
}

export default App;

Now you should see screen with a title Login Page . Now , let’s go on and create our login page , inside src folder create pages directory and inside pages directory a LoginPage directory with LoginPage.js and LoginPage.css files as below :-

src/pages/LoginPage.js

import React from "react";
import logo from "../../assets/logo.png";
import "./LoginPage.css";

const LoginPage = () => {
  return (
    <>
      <div className="login">
        <div className="login__header">
          <img src={logo} alt="whatsapp logo" className="login__header__logo" />
          <div className="login__header_title">Whatsapp Web</div>
        </div>

        <div className="login__content">
          <div className="login__content__row">
            <div className="login__content__row__description">
              <h1>To use WhatsApp on your computer:</h1>
              <ol>
                <li>
                  We need your mobile number so as we can create your account .
                </li>
                <li>
                  Click verify to receive sms verification and proceed to login
                </li>
                <li>Chat with other registered users </li>
              </ol>
            </div>
            <div>
              <h1>Firebase Auth Here</h1>
            </div>
          </div>
        </div>
      </div>
    </>
  );
};

export default LoginPage;

Don’t forget to add a logo inside src directory , create assets folder then put logo.png . Also copy below code and paste inside LoginPage.css file

.login {
  display: flex;
  flex-direction: column;
  z-index: 2;
  align-items: center;
  justify-content: flex-start;
}

.login::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  z-index: -1;
  height: 222px;
  background: #00bfa5;
  width: 100%;
}
.login__header {
  margin: 25px auto;
  width: 1050px;
  display: flex;
  justify-content: flex-start;
  align-items: center;
}
.login__header__logo {
  max-width: 40px;
  height: auto;
}

.login__header_title {
  text-transform: uppercase;
  margin-left: 10px;
  color: white;
  font-size: 14px;
  font-weight: 500;
}

.login__content {
  background: white;
  border-radius: 3px;
  box-shadow: 0 17px 50px 0 rgba(0, 0, 0, 0.19),
    0 12px 15px 0 rgba(0, 0, 0, 0.24);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  color: #525252;
}

.login__content__row {
  display: flex;
  padding: 64px 60px 110px;
}

.login__content__row__description {
  max-width: 556px;
  padding-right: 30px;
}
.login__content__row__description h1 {
  font-size: 28px;
  font-weight: 300;
  margin-bottom: 52px;
}
.login__content__row__description ol li {
  font-size: 18px;
  color: rgb(74, 74, 74);
  margin-bottom: 18px;
}
.login__content__row__qr {
  max-width: 300px;
}
.login__content__row__register {
  display: flex;
  flex-direction: column;
  margin: 20px 10px;
  max-width: 200px;
  width: 100%;

  border: 1px solid #ccc;
  padding: 10px;
  border-radius: 10px;
}

.login__content__row__register input {
  padding: 13px 16px;
  border: 1px solid #ccc;
  border-radius: 4px;
  margin-bottom: 15px;
}
.login__content__row__register input:first-child {
  margin-top: 20px;
}

Now that we have our LoginPage done , go on and import it inisde App.js file as below :-

import "./App.css";
import LoginPage from "./pages/LoginPage/LoginPage";

function App() {
  return (
    <div className="App">
      <LoginPage />
    </div>
  );
}

export default App;

Now , our app should look as below :-

Login Screenshot 01

Now , let’s continue to add Firebase Authentication .

  1. proceed to firebase console at https://console.firebase.google.com/u/0/ ,
  2. click add project then enter project name , in this case whatsapp web clone then click continue .On step 2 , we can skip google analytics and click create a project .
  3. Once Your new project is ready , click continue . Now you should see firebase dashboard like below ;-

Firebase Homescreen

  1. On the above screen , below Get started by adding Firebase to your app choose web , the next icon after android icon .
  2. Now enter your app nickname then click Register App .

Firebase Create Web App

  1. Now you should see add Firebase SDK screen , from there copy firebaseConfig and initializeApp function to App.js file , see below . replace firebaseConfig with your config :-
import "./App.css";
import LoginPage from "./pages/LoginPage/LoginPage";

// Your web app's Firebase configuration
var firebaseConfig = {
  apiKey: "AIzaSyDuF-XXXXXXXXXXXXXX-54",
  authDomain: "whatsapp-web-clone-XXXXX.firebaseapp.com",
  projectId: "whatsapp-web-clone-XXXXX",
  storageBucket: "whatsapp-web-clone-XXXXXXX.appspot.com",
  messagingSenderId: "XXXXXXXXXX",
  appId: "1:XXXXXXXXXXXXX:web:303e0315f11ebc31de5469",
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);

function App() {
  return (
    <div className="App">
      <LoginPage />
    </div>
  );
}

export default App;

Now , if your project is running , you should see an error

src/App.js
  Line 14:1:  'firebase' is not defined  no-undef

Simple , let’s go on and install firebase via npm by running below command : -

npm install firebase

After installation is finished , add import firebase below the last import

import firebase from "firebase";

If everything goes well , the error should be gone .

Now that we have our firebase up and running , it’s time to add Firebase Aunthentication .

  1. Go to your firebase console , then select Authentication menu .
  2. Click Get Started to proceed to the next screen
  3. Under Sign-In Method , click Phone , then enable then click Save .
    Note : At somepoint i was getting error updating phone on saving , which could not figure out but when i came back after sometimes i manage to save .

Now that Phone Sign-In Method is enabled , let’s get back to our code and finish logging in the user .

To login the user , we will use a package called react-firebaseui which is basically react Wrappers on top of the Firebase UI Web library and notably Firebase UI Auth.

FirebaseUI Auth provides a drop-in auth solution that handles the UI flows for signing in users with email addresses and passwords, and Identity Provider Sign In using Google, Facebook and others. It is built on top of Firebase Auth.

Let’s go on and install it .

npm install react-firebaseui

Let’s proceed to add our authentication . Go to LoginPage.js and import FirebaseAuth Component as below

import { FirebaseAuth } from "react-firebaseui";

in or case , FirebaseAuth will pass two props uiConfig and firebaseAuth which is just a firebase auth method called via firebase.auth()

add uiConfig file after imports in LoginPage.js as below:-

// Configure FirebaseUI.
const uiConfig = {
  // Popup signin flow rather than redirect flow.
  signInFlow: "popup",
  // We will display Phone as auth providers.
  signInOptions: [firebase.auth.PhoneAuthProvider.PROVIDER_ID],
};

Now that we have our UI Config , we can go on and replace

Firebase Auth Here

with our firebaseAuth component as below:-

  <FirebaseAuth
                uiConfig={uiConfig}
                firebaseAuth={firebase.auth()}
           />

Now , our LoginPage.js file should be as below : -

import React from "react";
import firebase from "firebase";
import { FirebaseAuth } from "react-firebaseui";
import logo from "../../assets/logo.png";
import "./LoginPage.css";

// Configure FirebaseUI.
const uiConfig = {
  // Popup signin flow rather than redirect flow.
  signInFlow: "popup",
  // We will display Phone as auth providers.
  signInOptions: [firebase.auth.PhoneAuthProvider.PROVIDER_ID],
};

const LoginPage = () => {
  return (
    <>
      <div className="login">
        <div className="login__header">
          <img src={logo} alt="whatsapp logo" className="login__header__logo" />
          <div className="login__header_title">Whatsapp Web</div>
        </div>

        <div className="login__content">
          <div className="login__content__row">
            <div className="login__content__row__description">
              <h1>To use WhatsApp on your computer:</h1>
              <ol>
                <li>
                  We need your mobile number so as we can create your account.
                </li>
                <li>
                  Click verify to receive sms verification and proceed to login
                </li>
                <li>Chat with other registered users </li>
              </ol>
            </div>
            <div>
              <FirebaseAuth
                uiConfig={uiConfig}
                firebaseAuth={firebase.auth()}
              />
            </div>
          </div>
        </div>
      </div>
    </>
  );
};

export default LoginPage;

And We should see a screen as below : -

Whatsapp web clone Login Screen

Now , you can proceed with Sign-In , when you get sms and succesfully verify the code , our FirebaseAuth will dissaper , and that’s it . What needs to happen is handling login and to do that we will call onAuthStateChanged method of firebase auth on component mounting . Add code below inside LoginPage : -

 useEffect(() => {
    firebase.auth().onAuthStateChanged((user) => {
      if (user) {
        console.log("Success Login + user = ", user);
      } else {
        console.log("Not logged In ");
      }
    });
  }, []);

Now reload the page and see what your getting . If your getting Success Login in console , try relaunch the app in incognito to log yourself out .

If everything went well , and you have verify the code sent via sms you should be able to see Success Login message in your console .

At the moment you should have LoginPage.js as below : -

import React, { useEffect } from "react";
import firebase from "firebase";
import { FirebaseAuth } from "react-firebaseui";
import logo from "../../assets/logo.png";
import "./LoginPage.css";

// Configure FirebaseUI.
const uiConfig = {
  // Popup signin flow rather than redirect flow.
  signInFlow: "popup",
  // We will display Phone as auth providers.
  signInOptions: [firebase.auth.PhoneAuthProvider.PROVIDER_ID],
};

const LoginPage = () => {
  useEffect(() => {
    firebase.auth().onAuthStateChanged((user) => {
      if (user) {
        console.log("Logged In user = ", user);
      } else {
        console.log("Not logged In ");
      }
    });
  }, []);

  return (
    <>
      <div className="login">
        <div className="login__header">
          <img src={logo} alt="whatsapp logo" className="login__header__logo" />
          <div className="login__header_title">Whatsapp Web</div>
        </div>

        <div className="login__content">
          <div className="login__content__row">
            <div className="login__content__row__description">
              <h1>To use WhatsApp on your computer:</h1>
              <ol>
                <li>
                  We need your mobile number so as we can create your account.
                </li>
                <li>
                  Click verify to receive sms verification and proceed to login
                </li>
                <li>Chat with other registered users </li>
              </ol>
            </div>
            <div>
              <FirebaseAuth
                uiConfig={uiConfig}
                firebaseAuth={firebase.auth()}
              />
            </div>
          </div>
        </div>
      </div>
    </>
  );
};

export default LoginPage;

Now that we can login , were ready to start chatting , right ? Yes , just one thing left which is setting a flag to check if user is LoggedIn , for now we will use useState . add below code just after the start of our LoginPage : -

const [isLoggedIn, setIsLoggedIn] = useState(false)
const [user, setUser] = useState("");

Now if user login is succes we can set isLoggedIn to true and user to user’s phoneNumber

 if (user) {
        console.log(user);
        setIsLoggedIn(true);
        setUser(user.phoneNumber);
      }

Now in our LoginPage we can check if isLoggedIn is false , and display a login screen or else for now we will have a heading that says “Welcome to whatsapp Web {userPhoneNumber} ” as below:-

import React, { useEffect, useState } from "react";
import firebase from "firebase";
import { FirebaseAuth } from "react-firebaseui";
import logo from "../../assets/logo.png";
import "./LoginPage.css";

// Configure FirebaseUI.
const uiConfig = {
  // Popup signin flow rather than redirect flow.
  signInFlow: "popup",
  // We will display Phone as auth providers.
  signInOptions: [firebase.auth.PhoneAuthProvider.PROVIDER_ID],
};

const LoginPage = () => {
  const [isLoggedIn, setIsLoggedIn] = useState(false);
  const [user, setUser] = useState("");

  useEffect(() => {
    firebase.auth().onAuthStateChanged((user) => {
      if (user) {
        console.log(user);
        setIsLoggedIn(true);
        setUser(user.phoneNumber);
      } else {
        console.log("Not logged In ");
      }
    });
  }, []);

  return (
    <>
      {!isLoggedIn && (
        <div className="login">
          <div className="login__header">
            <img
              src={logo}
              alt="whatsapp logo"
              className="login__header__logo"
            />
            <div className="login__header_title">Whatsapp Web</div>
          </div>

          <div className="login__content">
            <div className="login__content__row">
              <div className="login__content__row__description">
                <h1>To use WhatsApp on your computer:</h1>
                <ol>
                  <li>
                    We need your mobile number so as we can create your account.
                  </li>
                  <li>
                    Click verify to receive sms verification and proceed to
                    login
                  </li>
                  <li>Chat with other registered users </li>
                </ol>
              </div>
              <div>
                <FirebaseAuth
                  uiConfig={uiConfig}
                  firebaseAuth={firebase.auth()}
                />
              </div>
            </div>
          </div>
        </div>
      )}
      {isLoggedIn && <h1>Welcome to whatsapp Web {user}</h1>}
    </>
  );
};

export default LoginPage;

If you manage to login and see the message Welcome to whatsapp Web , then you are a champ and congrats for making up to this part .

For now let’s end here , in Part 2 of this tutorial series we will start working on our Chat Page , creating all screens , start sending messages , setting up the backend with Express as well as managing our app data with Context API .

Hope you learn something and don’t hesitate to share any feedback .

Buy Me A Coffee

Robert Rutenge
Front-end Developer | ReactJS enthusiast | Problem Solver . Find me on twitter and Github