Creating backend for messaging app

At the beginning of my journey with React Native, building a chat app was a challenge for me. I thought that application development would be complicated and time-consuming. I couldn’t be more wrong! I’ve started acquiring knowledge that I needed to make simple chat app, then created a repository and it just happened!

I want to share with you what I have learned over the course of past months in series that consists of the following topics:

What tools do you need?

First of all, we need a server. I have decided to use Hapi.js. Now, if you haven’t heard of it before, it’s a declarative configuration-centric framework. What does it mean? Unlike Express.js, which relies heavily on the concept of middlewares, Hapi.js gives you an opportunity to pass the configuration object that describes your route hierarchy.

Here’s how a typical setup would look like:

What’s great about this approach is the ability to describe the endpoints your application supports and an opportunity to reuse it across your different projects.

Let’s start by adding Hapi.js to our dependencies:

NOTE: You can use npm instead.

Next, we need a database to store our users and their conversations. I chose MongoDB. Thanks to being NoSQL, it’s structure is similar to JSON objects, which makes it easy to navigate through the data. To define the schema for documents, we will use object modeling tool called Mongoose.

It’s necessary to install Mongo:

And finally, we will need Socket.IO, which is a library that helps you to work with WebSockets. We will use it to implement real-time communication with our server, including receiving and ending data to connected sockets.

Setting up

Let’s create a server based on Hapi.js. It allows us to handle http protocol and Socket.IO. Next step is to listen to ‘connection’ event, which is automatically sending by the client. Then on ‘init’ assignto socket sending user’s id from sockets object. Now, we just listen to ‘message’ event that is sent from the client when the user sends a message. The message is directly transferred between two defined sockets. Simultaneously, when the app is closed, the ‘disconnect’ event is fired.

Every endpoint needs its own route with a specific handler, so we need to define it. The route could be something like:

Conversation or message?

At this stage, we need to catch the difference between conversation and message. Conversation is a container for messages (has a reference to the message model) being sent between two users.

Message model object should be similar to the one below:

Create a converations as a first handler

I’m sure you have noticed that first handler has to be responsible for creating conversation. Let’s dive into it. First, you need to make sure that there has been no conversation between the two users yet. Creating a conversation includes adding new conversation object to the database for two messaging users. It looks easy! But is it really? Take a look at more handlers.

… and more handlers

The container is ready for an initial message. To create it, we need to find a proper conversation by an id, which is sent from a client in message property. Then, we are able to create a textMessage, save it and push to the messages array as a part of a conversation model.

What should we do next? Imagine a case when your user starts a conversation, sends a new message and closes the app. Suddenly, he realizes he forgot to mention something important, so he re-opens the app… and gets confused: there is no conversation and no messages. Don’t worry, they’re not lost — they still exist in the database, waiting to be loaded. Naturally, we expect only a conversation with the chosen friend to load, so we need to distinguish two ids and reply the proper one extended with conversation id.

Closing the app’s backend, we need to implement the last handler related to loading messages for a given conversation id.

Hooray, we’re done and our backend is set! 🎉

If you’re interested in how to connect our work with frontend — make sure to follow this series, because there’s another article coming up in December. Everything you read today, you can check out in my repo. Enjoy!

May the force be with you…