How I build a desktop chat app with CometChat and NW.js (and how you can too)
Last updated: Oct 24, 2024
Chat Screen
This is not your typical "paste this here" and "paste that there"-type tutorial (you can find plenty of those here on cometchat.com/tutorials). While those tutorials certainly have merit, I am going to share my thought process from beginning to end.
The application I built is simple enough. When someone loads the app, they are prompted to enter their username and begin chatting:
The application ultimately runs on Node with help from NW.js (previously known as node-webkit). NW.js is advantageous because it enables us to code cross-platform desktop applications using our favorite web technologies. For this application, I chose to use React and Redux.
The back-end logic - from sending and receiving messages in real-time to populating what I call the "participant list" - is powered by CometChat. You will learn more about CometChat as you read on.
This post is not intended to be a walkthrough. Although I will be explaining the technical components of this application, my main ambition is to help you think through a solution from beginning to end. Hopefully, when you finish this post you'll be a slightly better developer and consider CometChat for your growing tool belt.
Just want the example code?
You may see the source code here. There is also a detailed README, where you will find all the information you need to install, run and test the app.
Because the desktop app is built using web technologies, it is entirely possible to run it in your browser. Towards the end of this post, I will show you how to deploy the app on Netlify.
Planning
In this section we have to decide what components will we need to build. What functionality will they have? In other words, what are the questions we need to answer, to plan the building process?
Let’s step back for a while and think. Try asking yourself the questions who will take us to the structure we need for our app.
Below I am going to lay out my questions and the answers. This is the process of the actual building the structure of the app, but in your head first. Keep in mind that it happens very often such that when answering a question new questions appear. This was the case with me as well.
Questions:
Answers (following the order of the questions):
Features
I have decided to implement the following features to the demo app:
Front End — React
We are going to use React to build our user interface. Below, I am going to list the components I have created and a short explanation about each of them:
Here a visual representation of the app components:
State Management — Redux
Every modern application these days has a state. Place in the memory where the application is storing certain data for later use. For our application state management, we use Redux. Of course, for a simple app like this, we could go without using Redux at all. But, from the learning point of view (after all we all do this for learning new stuff, right?), I think it would be nice to see the whole cycle of sending a request to an API, going through a middleware (redux-thunks) and getting the response recorded to the state. And we will manage this state by using Redux.
How it works
The main building blocks in a Redux app are called reducers — small functions used for managing the state. Simply said, what they do is accepting the old state object as input and, depending on certain actions (which are also passed in the same input), returning new state object. The new state could be changed in full or just partially.
In our app, we have three simple reducers, which are responsible for those parts of the state, responsible for the users’ list, the login process and sending/receiving messages. All of them can be seen in /src/reducers folder, along with a file containing the initial state of our app.
Redux, as state management library, can be used with any other UI framework, practically every app that needs to have a state can benefit from using Redux. If you want to go deeper, start from their website and follow along.
Side Effects Handling — Redux Thunks
One of the best known approaches for managing side effects in a redux app is called redux-think. This is what we use in our application as well. If you want to learn more details about redux thunks and how to use them, I recommend their website as a starting point and then build a small application, like this one for example :).
In our project, in /src/actions folder, is where I put the thunks used in the demo application. And in /store directory is where the configurations for the redux store live.
Make it desktop — NW.js
The part of our application that makes it possible for our app to run on desktop is taken care of by a library called NW.js. Remember that we are building a desktop application. Exactly the desktop part is going to be implemented via NW.js. Similar to Electron, another library for building desktop applications, NW.js provides a way to the developers to use their web skills to build applications that can run on a desktop. This means you can still use your JavaScript/React skills when building an app and then leverage the power of the desktop operating system via Nw.js APIs. In other words, Nw.js gives you the ability to make a skeleton app, which can be “filled” with your UI, no matter what library you have used to create it. And the best thing is that such an app has access to Node.js/NW.js APIs and the DOM in the same JavaScript context.
Since we mentioned the other big player in the field of building cross-platform desktop apps, let me give you a brief comparison between the two.
Nw.js vs Electron
Chat — CometChat
The usage of CometChat API is pretty straight-forward. It’s a RESTFull API, on which is built another layer of abstraction - CometChat SDK. It allows us to call directly exposed methods for different actions we might want to perform, such as send. Here an example of such a method:
return CometChat.sendMessage(textMessage).then(
message => {
console.log("Message sent successfully:", message);
return message;
},
error => {
console.log("Message sending failed with error:", error);
}
);
You may see all the Chat API logic in /src/chat-api folder. There you will also see the mocks I created, which allow us to test our app without real connection to the API.
Improvements
Every project deserves some thoughts after finishing the first phase. One part of this thought process would be dedicated to how it went, what was good and bad, and what might be done better. And one part would be dedicated to thinking about possible improvements. Here are a few ideas for our case. If someone goes to this direction and implement any of these for real, please do not forget to let me know :)
Deploy on Netlify
To deploy your application to Netlify platform you need to create an account first. Go to their website and sign up for new account. After that go ahead and login. While still under Sites section, you should see a button for deploying new site from Git.
Click it and follow the steps to create a new site for deployment from your GitHub repositories. Your process should be similar to what is shown in the image below.
Now, the last step before having your app deployed is to make sure you have the correct build commands and environment variables in place. To do that, after you create your site for deployment, go to Build & deploy settings screen and enter the following (don’t forget to use your repo URL):
Under Environment section is where you need to enter the environment variables as defined in your .env file. Here is how it looks mine:
Note: I have erased the values as this is supposed to be private info and you should not share yours as well.
That should be enough for you to have your app deployed on Netlify. Keep in mind the Deploys default settings are set to ‘auto publishing’, which means that it will trigger a deploy on each commit you do to the master branch in your repo. This is the place where you can trigger a deploy manually as well. This is how my Deploys screen looks like:
Conclusion
In this tutorial, we saw how can we leverage our web development skills to create applications that can run on a desktop. What we built is a demo application, that lacks a lot of a fully-featured-production-ready app features, but when one wants to learn and share, this would do the job. If you would like to deepen your knowledge in this direction, I would recommend you to try to improve it, by implementing features that are more likely to be seen in a real desktop application.
There are plenty of opportunities to explore out there, I hope this tutorial entertained you enough to keep your flame of curiosity burning even more.
🔥 Thanks for reading! 🔥
Notes:
Resources: