BuzzLine is a feature-rich messaging and calling web application.
After learning Node.js, I wanted to put my skills to the test and build something amazing. I decided to go with the good ol' messaging app.
The very first thing that had to be done was to design the frontend. I wanted to make it look modern and sleek, yet simple and easy to use. I fired up Figma and started designing. After a few days of work, I had something I was happy with. Time to code!
At the core of the server side is Express.js. I used it to create a REST API for the frontend to consume. Authentication is handled by Passport.js and JWT. The process looks like this: when a user logs in, two tokens are generated - access token and refresh token. The access token is used to authenticate the user on every request. It expires after 20 minutes. The refresh token, which is valid for 7 days, is used to generate a new access token when the old one expires. Another important part of the backend is Socket.IO - a library that enables real-time, bidirectional communication between the browser and the server. It is the backbone of the chat functionality. It was my first time using it, so I had to do a lot of researching and googling to get it working properly. It accommodated real-time message delivery, notifications, and tracking users' online status, along with providing information about their current message input activity. Last but not least is the use of the Cloudinary SDK for file upload. It also played a crucial role in the application. It was used to provide users with the ability to upload avatars, send images and voice clips. The whole backend is written in TypeScript.
For the client side, I used my favorite framework - Next.js. It consumed the API with the help of Axios and TanStack Query (formerly known as React Query). It was also my first time using these, but it was pretty easy to get the hang of it. One challenge I faced was to implement automatic request retries when the access token expired. I solved this by using Axios interceptors. To persist fetched data, I used a state-management library called Zustand. To provide the messaging functionality, I used Socket.IO on the client side as well. Audio/video calling was integrated using the Peer.js library - a wrapper around the native WebRTC API. Just like the backend, the frontend is written in TypeScript and styled with TailwindCSS.
To sum up, this project was probably the most challenging I've ever done. However, it was also the one that taught me the most. I learned a lot about authentication, authorization, WebSockets and WebRTC, uploading to the cloud, state management and so much more. It introduced me to a lot of new technologies I know I can count on in the future.