In this blog, we’ll build a real-time chat application using Socket.io for bi-directional communication, Express.js for the server, React.js for the frontend, and Chakra UI for styling. We'll set up the project using Vite for fast development.
Key Features:
- User ID based chat: A random userId is generated and stored in session storage.
- Message display: Our messages appear on the left, and others' appear on the right, each with an icon.
Here is the demo of this project :
Let’s get started!
1. Setting Up the Project
Create A wrapper folder chat-app where our front-end and back-end resides:
mkdir chat-app
cd chat-app
Backend Setup: Express.js with Socket.io
First, create a folder for your backend and initialize it with npm init -y:
mkdir chat-backend
cd chat-backend
npm init -y
Now install the necessary packages:
npm install express socket.io
Create the following file structure for the backend:
chat-backend/
│
├── server.js
└── package.json
server.js
- Express and Socket.io
Here’s how to set up the Express server with Socket.io:
const express = require('express');
const http = require('http');
const { Server } = require('socket.io');
const app = express();
const server = http.createServer(app);
const io = new Server(server, {
cors: {
origin: 'http://localhost:5173',
methods: ['GET', 'POST']
}
});
io.on('connection', (socket) => {
console.log('A user connected:', socket.id);
socket.on('sendMessage', (message) => {
io.emit('receiveMessage', message);
});
socket.on('disconnect', () => {
console.log('A user disconnected');
});
});
server.listen(4000, () => {
console.log('Server listening on port 4000');
});
This code creates an Express server that listens on port 4000
and sets up Socket.io
to handle real-time communication. When a user sends a message (sendMessage event), it's broadcast to all connected clients.
Frontend Setup: Vite with React and Chakra UI
Create a Vite React project and follow below screenshots (create project in chat-app
and not in chat-backend
):
npm create vite@latest
Navigate into the project folder and install the necessary dependencies:
cd chat-frontend
npm install socket.io-client @chakra-ui/react @emotion/react @emotion/styled framer-motion
Now, let's create a basic structure for our chat application.
2. Implementing the Chat Frontend
The following will be the structure for the frontend:
chat-frontend/
│
├── src/
│ ├── components/
│ │ └── ChatBox.jsx
│ ├── App.jsx
│ └── main.jsx
├── index.html
└── package.json
App.jsx
In App.jsx
, set up Chakra UI and render the ChatBox component:
import { ChakraProvider, Box, Heading } from "@chakra-ui/react";
import ChatBox from "./components/ChatBox";
function App() {
return (
<ChakraProvider>
<Box p={5}>
<Heading as="h1" mb={6}>
Real-Time Chat
</Heading>
<ChatBox />
</Box>
</ChakraProvider>
);
}
export default App;
ChatBox.jsx
This is where the main chat logic will go. We’ll use Socket.io
to listen for messages and handle real-time updates. A random userId is generated and stored in session storage, and the chat UI is built using Chakra UI
.
import React, { useState, useEffect } from "react";
import { Box, Input, Button, HStack, VStack, Text, Avatar } from "@chakra-ui/react";
import { io } from "socket.io-client";
const socket = io("http://localhost:4000");
const ChatBox = () => {
const [messages, setMessages] = useState([]);
const [input, setInput] = useState("");
const [userId, setUserId] = useState(null);
useEffect(() => {
// Generate or get userId from session storage
let storedUserId = sessionStorage.getItem("userId");
if (!storedUserId) {
storedUserId = Math.random().toString(36).substring(7);
sessionStorage.setItem("userId", storedUserId);
}
setUserId(storedUserId);
// Listen for messages
socket.on("receiveMessage", (message) => {
setMessages((prevMessages) => [...prevMessages, message]);
});
return () => {
socket.off("receiveMessage");
};
}, []);
const sendMessage = () => {
if (input.trim()) {
const message = {
userId,
text: input,
};
socket.emit("sendMessage", message);
// setMessages((prevMessages) => [...prevMessages, message]);
setInput("");
}
};
return (
<VStack spacing={4} align="stretch">
<Box h="400px" p={4} borderWidth={1} borderRadius="lg" overflowY="auto">
{messages.map((msg, index) => (
<HStack key={index} justify={msg.userId === userId ? "flex-start" : "flex-end"}>
{msg.userId === userId && <Avatar name="Me" />}
<Box
bg={msg.userId === userId ? "blue.100" : "green.100"}
p={3}
borderRadius="lg"
maxW="70%"
>
<Text>{msg.text}</Text>
</Box>
{msg.userId !== userId && <Avatar name="Other" />}
</HStack>
))}
</Box>
<HStack>
<Input
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="Type a message"
/>
<Button onClick={sendMessage} colorScheme="teal">
Send
</Button>
</HStack>
</VStack>
);
};
export default ChatBox;
How It Works:
Random userId: We generate a random string as userId and store it in
sessionStorage
. This ensures that even if you reload the page, you'll retain the same userId for the session.Socket.io for messaging: The app listens for receiveMessage events from the server and displays incoming messages. When a user sends a message, it's emitted via
Socket.io
, and the UI updates in real-time.Chakra UI styling: Messages are displayed in a box, with our messages aligned to the left (with a blue background) and others’ to the right (green background). Each message also has an avatar for a simple, personalised chat interface.
3. Running the Application
Start the backend:
cd chat-backend
node server.js
Start the frontend:
cd chat-frontend
npm run dev
Now, open http://localhost:5173
in multiple browser windows to test real-time chat functionality. You’ll see each user's messages displayed with their unique userId
.
You’ve successfully built a real-time chat application using Socket.io, Express, React.js, and Chakra UI, with the project set up via Vite! 🎉
This app demonstrates the power of Socket.io for real-time communication 💬 and Chakra UI for a clean, responsive interface 📱.
You can expand this project by adding features like chat rooms 🏠, message persistence 💾, and user authentication 🔒.
That's all for this blog! Stay tuned for more updates and keep building amazing apps! 💻✨
Happy coding! 😊
Top comments (41)
This is a great starter app, but it would be really great, if you could show us how to set up an admin to multiple user chat app. So, there is one admin and he can chat with multiple users, but each user only sees his/her own messages & the response from the admin. The admin would be able to see all users in a list and then choose which user to interact with.
This would be a brilliant real world chat app tutorial, if you don’t think it’s too complicated.
Great idea !!
But I think it's good for Bootcamp but it's too complicated for covering this in blog.
I tried creating this app in Angular, it worked pretty well, but after a while messages started to leak to the wrong user.
As I remember I sent:
As
admin
, I could then choose which user to send a message back to.Of course if the
userid
in the client, doesn’t match then the message isn’t shown. But this seems a really inefficient way of pushing data. It would be far better to only send messages from theadmin
to a specific user.However, I guess this is impossible, because a websocket cannot broadcast to specific clients? Or can it, if we take advantage of the
room
feature? Maybe if aroom
has the same id as theuserid
, then this would work?@charlesr1971 , you can create room with specific id for example jobId and add only those user's to socket room which you want to.
Is it possible to push a message back to an individual client, if multiple clients are listening to the same socket?
From what I know, a message is broadcast to every client that listens and then it is up to the front end code to filter those messages out. Obviously the
userid
is sent back with every message and if this matches the clientuserid
, then the user can view that message.But if I can set each room to a specific
userid
then presumably it will send the response back to the correct user?But maybe I am misunderstanding how a
room
works?I did read that the socket automatically allocates an incoming message to its own
room
, which is represented by a random id.@jagroop2001 ,Your blog makes difficult tasks feel like a piece of cake.
Thanks for appreciation 🥳🧡.
It would be really helpful if you will react and share this with your friends.
@works is right.
@jagroop2001 , I'm skeptical that creating a chatting application is that simple. Thank you for sharing this fantastic blog.
Thanks @john12 🧡🧡
Seek for professional assistance from this tech guru on Telegram @prompttechrecovery, If you ever lost your funds in any online investment scheme, this tech guru is a pro for crypto investment loss recovery. He recently helped me recover from a cryptocurrency investment scam with great help. I owe him one.
Thank you for your comment, but it looks like this might be spam
thanks a lot for sharing
@mezieb You're welcome! 😊 I'm so happy my blog is useful for you!
yes i was integrating such functionality with socket.io,express in an angular project and you throwing more light to it help me structure things well.
@mezieb
I’m glad to hear that! Integrating with Socket.IO and Express in an Angular project sounds exciting. If you need any more tips or have questions, feel free to ask! 😊
Very Helpfull
@abdul_musavir_17097 , thanks .
If you really like my efforts please react and share.
It really motivates me to write more blogs.
Please "react" and share lol
Beautiful post right here, Thank you for putting this together
@web-dev-codi ,Thank you so much! I'm glad you liked it.
This was a sample and easy walk by through memory lane. I needed a refresher thank you .
Thanks @ronewaonly
Great, but I don't understand much... Only know NodeJS. By the way how to export console applications with it?
Thank !
However, I’m a bit confused about what you’re asking. Could you please clarify?
You're welcome. I mean how to set up everything like socket.io and the rest. Maybe make a video tutorial?
Great.
Thanks @neurabot