In this series of blog posts, we build a clone of the popular community-building app Discord using Next.js and our chat API and video SDKs. At Stream, our real-time communication SDKs echo Discord’s mission of uniting people. The aim of this project is to replicate Discord’s functional aesthetic appeal with our own services at the core.
We have broken it into five parts that focus on one specific feature at a time:
- Project setup using Next.js tooling and integrating Stream’s Chat SDK
- Building a fully custom server list
- Creating a collapsible list of channels combined with menu options
- Customizing the list of messages to match Discord’s style
- Add audio channels that can be transformed into video calls.
The full code can also be found on GitHub, so feel free to dive in and only read the code.
Part 1: Project Setup
In the first installment of this tutorial series, we guide you through the project's initial setup using the official Next.js tooling and best practices. This post lays the groundwork for the entire project, and we explore how to configure the necessary tools to work together in the best possible way.
We set up and initialize Stream’s React SDK and create the necessary architecture to log in as a user and gain access to all chat-related data. We also explore the Stream Dashboard to extract the necessary information for creating and setting up users.
Finally, we discuss the data structures we use in the project to map the channels to different servers and categories, just like in the Discord app. We finish up by creating a DiscordContext
object that works as a provider throughout the series, injecting all the necessary properties and functions into the lower-level components that we’re building.
Part 2: Server List
The second post in the series covers building the server list. We use a grid structure to build out the general layout of the Discord app that we’re copying.
We break up the server list into several parts, such as the direct messages, the real server icons, and a button to add new servers. We build out the UI for each of these items. Also, we figured out how to filter for the server the currently logged-in user is a part of. We finish things off by adding delight to the user interactions using animations.
Finally, we created a form for users to create new servers and kept it in the Discord design language. Users can invite others, name their servers, and switch between all the servers they are a part of. For this, we highly customized the complete experience from start to finish.
Part 3: Channel List
In the third part, we aim to display the channel list for a respective server. While Stream gives us a built-in way to do this, we want to customize this feature differently.
First, we need to filter for only the channels created for the currently active server, and then we break these up into categories. This comes hand-in-hand with the interaction paradigm of opening and closing certain categories, and we learn how to display the channels' messages when they are selected.
As for the server list, we add a form to create a new channel on the server. We reuse parts of the form logic we’ve created before and allow users to add others to new channels and give them custom names. We finish by adding a user bar at the bottom to add a personal touch.
Part 4: Message List
The fourth part of the series is all about the list of messages inside a channel. This covers customizing the channel header, building custom emoji reactions, creating a fully custom message composer, and even more components.
This marks the last chat customization posts and takes a different router for customization. We don’t change the overall structure of the layout, but simply change certain components with a fully custom UI. For that, we explore the different ways the SDK helps us in that regard and how we can inject our own custom components where we want and also leave some of the built-in components in place.
Part 5: Adding Audio and Video Calling
In the fifth and last part, we add the capability of audio channels to our Discord clone. We install Stream’s React Video SDK and configure it to work seamlessly with the Chat SDK.
We add the logic to create calls and the necessary data to transform them into audio channels in our UI. Then, we add a form to create new audio channels with a beautiful UI that matches the Discord design language.
Finally, we allow users to enter audio channels to talk to each other and even allow them to transform any audio call into a video call with one click. We re-use some of Stream’s built-in components to add powerful functionality for free, like screen sharing, emoji reactions, and recording calls.
Summary
In this series of tutorials, we demonstrate how to build a fully functional clone of Discord from scratch. In the video tutorial, we even added custom user signups with the help of Clerk.
We believe that this not only demonstrates the incredible powers that our SDKs offer, but it can also serve as a great tool for learning how to build such a complex project from the ground up with powerful features that we can fully tailor to our use case.
If you enjoy this series, consider giving the repository a star and let us know what you’re building next.