Using Firebase to create a chat app

Learning how to use firebase realtime database to create and model a simple chat app

Using Firebase to create a chat app
Firebase Logo.

I did not find a lot of content regarding how to model a working schema for real-time chat applications in NoSQL databases. So I spent a lot of countless hours trying to do it on my own. We are going to be using Google’s Firebase real-time database for the purpose of developing a simple chat app. This will be useful for both study and development purposes.

First of all why Firebase?

Google’s Firebase works the same as a JSON(JavaScript Object Notation) Object or Hash. These structures provide really fast access to read and write data, which is why we are using it for a chat app. It's also a great starting point to understand how event listeners work.

Pre-requisites: Node.js, NPM.

First, let’s create a project in Firebase.

After you have created your project, install firebase to your app using

$ npm install firebase --save

Import to your file (ES6)import firebase from "firebase";

Go to Firebase Console and check your project’s web configuration

Authentication --> Web Configuration, it should look something similar to this:

var config = { 
  apiKey: "YOU PROJECTS API KEY", 
  authDomain: "<PROJECT_ID>.firebaseapp.com", 
  databaseURL: "https://<DATABASE_NAME>.firebaseio.com", 
  storageBucket: "<BUCKET>.appspot.com", 
};

Paste the code in your file and then write: firebase.initializeApp(config); at the end. This establishes the connection with the firebase instance.

Now let's go to the Firebase Console and create the first 2 child refs, users, and messages.

We can access both locations or references by defining:

const users = firebase.database().ref("users");
const messages = firebase.database().ref("messages");

Now we need to populate these with users and messages. We first need some kind of user to start with, so go to firebase --> Authentication --> Add User.

A new user instance has an identifier like email, date of creation and a UID, which is what we are going to be using for the purpose of this guide. To get the UID in your file, do:

const userId = firebase.auth().currentUser.uid;

Writing/Updating Data

  • .set: Writes or replaces data to a defined path, (this option replaces everything on the path, so beware)
  • .update: Updates some of the keys for a defined path without replacing all of the data
  • .push: Adds to a list of data in the database. Every time you push a new node onto a list, your database generates a unique key, like: messages/<unique-conversation-id>/<message object>

Let’s get a unique id for our conversation.

const conversationKey = messages.push().key;

This returns a time-stamped based firebase token (always different) and we use it to create and access a conversation in both messages ref and users ref at the same time. That is because messages will hold all the conversations and their messages, and users will hold the keys to those conversations.

On the other side, we could also define a chatMessage object containing the data we want to pass to that message:

const chatMessage = { 
    type: "TEXT", 
    message: "Hello World!", 
    senderId: "userId" 
};

Now writing data to the ‘users’ node and the ‘messages’ node.

users.update(`/${userId}/conversations/${conversationKey}`);

messages.update(conversationKey).push(chatMessage);

This will create a new node called ‘conversationKey’ with a new Key for the message, containing the object we passed.

As seen above ideally we would have two users interacting with each other, through the same conversation.

Reading/Listening Data

  • .on: listens to data change constantly on the specified ref.
  • .once: listens just once to the specified ref.

Both methods should be called with the corresponding parameters, and a callback function, returning a snapshot value. You can use the value event to read a static snapshot of the contents at a given path. This method is triggered once when the listener is attached and again every time the data, including children, changes. The child_added event is similar, it is triggered when a new child is added to the ref to which this listener was added.

Suppose we have an objectconvMessages = {} in which we are going to store the conversation between the two users.

messages.child(conversationKey).on('value', (snapshot) => {

i.key would be the message id. We are reading the database and constructing the same object in ourconvMessages

We should now have something like:

convMessages = { 
    9348uhsfj8394jn: { 
        message: "Hello World!", 
        senderId: "

And because we are using the .on(‘value’, callback()) method we are going to be listening to changes on that ref and repopulating our convMessages object every time there's a new message pushed to the node.

Final Note

This is just one of the multiple ways to model a simple chat app in Firebase. You should now have an idea of how to build the relations for this type of apps in any other Non-relational or hierarchical database.

Feel free to check out more about this powerful system on the Firebase Docs.

Also, for more information about modeling in NoSQL, check out this fantastic guide:

https://highlyscalable.wordpress.com/2012/03/01/nosql-data-modeling-techniques/

Firebase videos are available on Youtube too!

https://www.youtube.com/watch?v=WacqhiI-g_o&list=PLl-K7zZEsYLlP-k-RKFa7RyNPa9_wCH