Firebase WhatsApp Clone Built With Flutter in No Time!

Firebase category image

I built a WhatsApp clone with Flutter and Firebase in a few hours. Here is what I came up with.

There are a ton of messaging apps available. Some well-known players are WhatsApp, Threema, Signal, and others. Apart from a messaging functionality, they provide many other features like group chats, file transmission, or data backup. In my little experiment, I tried to recreate the messaging feature that all apps use. My requirements were the following:

  • Two parties can send messages to each other
  • The user interface should look similar to other messaging apps
  • The client app is written with Flutter
  • The backend is Google Firebase

User management

I created basic data models in the beginning. They contain all the information that is relevant to the messaging system. First, we have a ChatUser object. It has an identifier, a name, and a list of chat identifiers. Why chat identifier? I’ll get to that later.

For authentication, I went with Firebase Authentication and its email/password authentication combination. It’s easy to implement and ensures that only registered users can write to my database. Uncontrolled data access can lead to huge bills! If you want even more security for your backend, try Firebase App Check!

View to register a new user with Firebase Authentication in the messaging system.
View to register a new user with Firebase Authentication in the messaging system.
View to log in an existing user with Firebase Authentication in the messaging system.
View to log in an existing user with Firebase Authentication in the messaging system.

The first screen is the login/register screen. The entire authentication is handled by Firebase Authentication. At no point, I can see the password! Chatting just requires a name that is displayed to other parties and an identifier to find the correct ChatUser object.

Here is the code to log in and register. In both cases, the Firestore collection users is accessed. During login, the matching ChatUser object is grabbed while during registration, the ChatUser object is created.

Join my free Medium Newsletter!

Get an overview of my new Medium content with my monthly newsletter. Save time and pick what you like to read!

Firestore collection with 3 users and their properties
Firestore collection with 3 users and their properties

This is how the users collection looks like in Firebase Firestore. The user identifier is also the document identifier which makes it easier to add filter clauses to the Firestore query. If I want to find a user with a certain id, I can look for the document with that id.

Listing and creating chats

After the login, the chat overview is loaded. It contains all chats and a button to start a new chat.

Overview of created chats in the Flutter Firebase Chat app
Overview of created chats in the Flutter Firebase Chat app

A Chat object is pretty simple, it contains an identifier, a list of ChatUser objects, and a list of ChatMessage objects. The identifier is the concatenation of the identifiers of the users. And this chat identifier is also stored in each ChatUser object.

When a new chat is created, then a new entry is added to the chats collection in Firestore. Also, the ChatUser objects are updated because their chat identifier collection gets a new entry.

Chats collection in Firebase Firestore containing an identifier, a list of messages, and a list of users (not in image).
Chats collection in Firebase Firestore containing an identifier, a list of messages, and a list of users (not in image).

When a User logs in and arrives at the chat overview, I use the list of chat identifiers that is stored alongside a User object to create streams. These streams update immediately and the user can see the latest message of every chat in the overview. I don’t want to load the entire chat message history yet but only the stream for fast updates. That’s why I decided to store chat identifiers with a User.

Writing messages

Writing messages is pretty easy since we have all the information we need. The SingleChatPage is attached to the stream of the chat collection with the given identifier. You can use a StreamBuilder widget for that purpose. It also takes care to dispose of the stream for you.

Adding a new message is reduced to adding a new message entry to the Chat object. First, I create it from the Firestore collection. Then, I add a new entry. And last but not least, I call the update method of Firestore to publish the changes.

Since the UI is attached to the chat stream, it reflects changes in an instant. Below you can see a screenshot of what it looks like:

Sending and receiving messages with a chat partner in Flutter Firebase Chat app.
Sending and receiving messages with a chat partner in Flutter Firebase Chat app.

Level up your Firebase skills!

Check out my free email course on Firebase fundamentals, and grab your copy of my Firebase ebooks. Start building amazing apps with Firebase today!

What does it look like?

Here is a video of the final example. In the background, you can see the database. I am writing messages from the app on my phone and have another instance running in the browser (left area of the video). As you can see, the chat is immediately updated when the database field is updated.

A Flutter Firebase Chat App demo video. The right area shows the Firebase Firestore documents and the left area is a running app instance in the browser.
A Flutter Firebase Chat App demo video. The right area shows the Firebase Firestore documents and the left area is a running app instance in the browser.

The next steps would be to add further functionality, eliminate some bugs, and improve the UI. In general, it is similar to known chat apps but it looks like it is a prototype. However, the goal was to implement a WhatsApp clone with Firebase and not make it a feature-complete and production-ready mobile app for every platform.

Possible enhancements

Here are some improvements that can be implemented to make the app even more useful. I did not do it because it wasn’t on the agenda. Feel free to get inspired.

? File and image transfer
Sending images and files is a crucial part of every messenger app today. This app can be easily enhanced to support these features by using Firebase Storage.

? Profile pictures
At the moment, users can only select their username during the registration process. Other personalization features are not implemented right now. Firebase Storage is also a perfect solution for this purpose.

? Group chats
This is also a frequently used feature. By design, the app supports group chats. It’s just not possible to select more than one chat partner currently.

? Push notifications
Get notified when a new message was posted in a chat. A very useful feature that can be implemented in various ways. Firebase offers this capability, too. Here’s my full guide to implementing notifications:

Easy Push Notifications With Flutter And Firebase!

A step-by-step guide for beginners to send and receive customized push notifications in Flutter apps backed by Firebase.

? Paging
When a chat is opened, all messages are downloaded. This might get slow if the message numbers grow. With paging, the bottleneck can be fixed. Paging means that only the latest chunk of information is retrieved. Previous data will only be grabbed if explicitly requested.

? Sound notifications
Messengers come with sound notifications for new messages, file transfers, or incoming calls. This could be implemented by adding small audio files to the Flutter project and playing them at the right moments. I don’t suggest storing them in the cloud or accessing them through HTTP requests because the delay might be high in some cases.

Bugs

The code is not bug-free. For example, if you start a new chat and send a first message, the UI is not updated. This is because there is no stream yet to subscribe to. There are also some bugs with the navigation when creating a new chat.

As it was an experiment, I didn’t invest much time in improving the user experience. But that can easily be fixed by anyone.

Additional resources

Here are some additional resources about Firebase in case you want to dive deeper into the topic.

Firebase Cloud Functions

Your all-in-one toolbox to building serverless infrastructures in the cloud. Write once and scale to infinity!

Firebase Cloud Storage

Upload and download user-generated content like on a file system. Firebase Cloud Storage makes file handling simple!

Firebase Remote Config

Real-time feature toggles or A/B testing are typical use cases of Firebase Remote Config. Learn how to implement them now!

Firebase Console

Learn how to manage projects, apps, users, billing plans, and costs with step-by-step guides in the Firebase Console.

Firebase Cloud Firestore

Learn about Firebase Firestore and write mobile apps with the power of a modern and fast NoSQL database.

Firebase Authentication

Implement email/password authentication or use social providers like Google, Microsoft, and Facebook for your apps!

Firebase Hosting

Host your web apps, microservices, dynamic, and static content with this powerful yet simple solution from Firebase!

Conclusion

Creating a messaging app like WhatsApp with Flutter and Firebase was easier than I thought. In fact, I spent most of the time with the user interface and not with the messaging logic or the Firebase backend. And it was a lot of fun. Of course, it’s not suited for a large user base but the concepts are quite clear to anybody.

Source code

You can find the source code on GitHub. The repo contains the working app without the Firebase configuration. You need to create the account and link your app with it. Then you can reproduce all the results of this article.

Related articles