In today’s web landscape, users expect instant feedback-whether it’s receiving a new chat message, seeing a real-time stock price update, or getting notified when someone comments on a post. This shift has made real-time communication essential for modern applications.
In this beginner-friendly tutorial, we’ll explore how to build real-time features in a Next.js app using Socket.IO. You’ll understand the fundamentals, build a simple real-time chat, and learn how to integrate Socket.IO cleanly into a Next.js environment.
What Is Socket.IO?
Socket.IO is a JavaScript library that facilitates real-time, bi-directional communication between web clients and servers. It uses WebSockets under the hood but adds many improvements:
- Fallback mechanisms: Works even when WebSockets aren’t supported (e.g., via long-polling)
- Event-based communication model
- Automatic reconnection
- Broadcasting support
This makes it ideal for applications like:
- Chat systems
- Live notifications
- Multiplayer games
- Online collaboration tools
- Real-time analytics dashboards
Why Use Socket.IO with Next.js?
Next.js, as a full-stack React framework, offers static and server-side rendering, routing, API routes, and more. But real-time communication isn’t built-in. That’s where Socket.IO fits perfectly.
Benefits of using Socket.IO with Next.js:
- Easily integrates with custom Express servers
- Allows you to build both the frontend and backend in one unified project
- Provides a seamless developer experience with React
Project Setup: A Real-Time Chat App
Let’s build a basic chat app to demonstrate real-time messaging
Step 1: Create a New Next.js App
Let’s start with a fresh project. Open your terminal and run:
npx create-next-app@latest nextjs-socketio-chat cd nextjs-socketio-chat
Step 2: Install Required Packages
We need socket.io for the server and socket.io-client for the frontend. We’ll also use Express to create a custom server:
npm install express socket.io socket.io-client
Step 3: Setup a Custom Express Server
Next.js supports custom servers for extending its capabilities. Here’s how to create one with Express and integrate Socket.IO.
Create a file called server.js:
const express = require('express');
const next = require('next');
const { createServer } = require('http');
const { Server } = require('socket.io');
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
app.prepare().then(() => {
const expressApp = express();
const server = createServer(expressApp);
const io = new Server(server);
// Real-time communication logic
io.on('connection', (socket) => {
console.log('A user connected:', socket.id);
socket.on('chat-message', (msg) => {
io.emit('chat-message', msg); // broadcast to all clients including sender (if you want to broadcast to all client excluding sender, you have to call socket.emit function instead of io.emit function)
});
socket.on('disconnect', () => {
console.log('User disconnected:', socket.id);
});
});
expressApp.all('*', (req, res) => handle(req, res));
server.listen(3000, () => {
console.log('> Server running on http://localhost:3000');
});
});
Step 4: Modify package.json Scripts
Update your package.json to use your custom server:
"scripts": {
"dev": "node server.js", …
}
Run the development server:
npm run dev
Step 5: Build the Frontend Chat Component
Create a file: src/components/Chat.tsx
"use client";
import { useEffect, useState } from "react";
import { io } from "socket.io-client";
const socket = io();
export default function Chat() {
const [message, setMessage] = useState("");
const [chatLog, setChatLog] = useState< {
message: string;
timeStamp: number
}[]
>([]);
useEffect(() => {
socket.on("chat-message", (messages) => {
setChatLog((prev) => [...prev, messages]);
});
return () => {
socket.off("chat-message");
};
}, []);
const handleSend = () => {
if (message.trim().length > 0) {
const timeStamp = Date.now();
socket.emit("chat-message", { message, timeStamp }); // you can add username or token also with this object after adding authentication flow
setMessage("");
} else {
alert("Please enter message");
}
};
return (
<div style={{ padding: "20px", maxWidth: "600px", margin: "auto" }}>
<h2>Real-Time Chat</h2>
<div style={{ display: "flex", gap: "10px" }}>
<input
value={message}
onChange={(e) => setMessage(e.target.value)}
placeholder="Type your message"
style={{
flex: 1,
padding: "10px",
border: "1px solid #ccc",
borderRadius: 5,
}}
/>
<button onClick={handleSend}>Send</button>
</div>
<ul style={{ marginTop: "20px", listStyle: "none" }}>
{chatLog.map((chat, i) => (
<li
key={i}
style={{
padding: 10,
border: "1px solid #ccc",
borderRadius: 5,
marginTop: 15,
}}
>
{chat.message}
<span style={{ display: "block", fontSize: 12, color: "#ccc" }}>- {new Date(chat.timeStamp).toLocaleString()}</span>
</li>
))}
</ul>
</div>
);
}
Step 6: Load the Chat Component in a Page
Update src/app/page.tsx:
import Chat from "@/components/Chat";
export default function Home() {
return (
<div>
<Chat />
</div>
);
}
Step 7: Test the Application
Start the server:
npm run dev
Open http://localhost:3000 in two tabs or two different browsers.
Send a message in one tab and it will instantly appear in the other.
Output:

Congratulations! You now have a working real-time chat app using Socket.IO and Next.js.
How Socket.IO Works Under the Hood
Socket.IO uses a publish/subscribe (pub-sub) pattern. Events like ‘chat-message’ act as channels that clients and servers subscribe to or emit.
Key Concepts:
- Socket: A persistent connection between the client and server
- Events: Custom named messages exchanged (chat-message, user-joined)
- Broadcasting: Send data to multiple clients at once
Unlike HTTP requests which are client-initiated, sockets keep the connection open both ways.
Advanced Socket.IO Features to Explore Later
- Rooms: Group sockets together to send targeted messages
- Namespaces: Create separate channels for different purposes
- Middleware: Add authentication before accepting socket connections
- Scaling: Use Redis adapter to scale Socket.IO across multiple servers
Common Use Cases in Next.js Projects
- Chat Applications: Support group or private messaging
- Live Notifications: Show instant updates like “New order placed”
- Collaborative Tools: Real-time whiteboards or documents
- Live Dashboards: Auto-updating sales, user, or stock data
- Gaming: Multiplayer games using sockets for live sync
Conclusion
Adding real-time features like chat, notifications, or live dashboards is easy and efficient when using Socket.IO with Next.js. With a custom server, dynamic client components, and event-driven messaging, you’re equipped to build responsive and interactive apps that users love.
Socket.IO’s ease of use, power, and flexibility make it a go-to solution for real-time web communication.
