create two folders client & server
two terminal instances for them
install nextjs in client directory
bunx create-next-app@latest . bun add socket.io-client
for backend:
npm init -y npm install express nodemon socket.io npx gitignore node
Client
create components/
Chat.tsx index.tsx Inputs.tsx SignUp.tsx the input file is a barrel Socket.io
- It is a library that allows low-latency, bidirectional & event-based communication between a client and a server
- It consists of two components a client and a server
- In the socket.io world the
iois the server instance
a socket is a single connection
Backend
Now add the follow script in the backend directory
- the following code starts a new server
- Make sure to start it on a different port other than the one next app is running on
const http = require("http"); const express = require("express"); const app = express(); const server = http.createServer(app); // this will be replaced by socket.io app.get("/", (req, res) => { res.send("Hello World!"); }); server.listen(3001, () => { console.log("Server is running on port 3001"); });
Then we need to start our socket io connection
this logs whenever there is a connection made from the client
// server/index.js const {Server} = require("socket.io"); const io = new Server(server, { cors: { origin: "*", } }) io.on("connection", (socket) => { console.log("Connect is established!") })
Make a client connection
- mark the page to client as later on we are going to utilize some of the client side functionality
"use client"; import { io } from "socket.io-client"; const socket = io("http://localhost:3001"); // make it to codespaces url socket.on("connect", () => { console.log("Connected to server"); }); export default function Home() { return <h1>Hello from Next.js</h1>; }
Then we can send some message to the server using useEffect (once the page loads up)
export default function Home(){ useEffect(() => { socket.emit("client-ready", "Hey do you see this message?") }, []) // rest of the code below return ... }
Listening on server end
// server/index.js const { Server } = require("socket.io"); const io = new Server(server, { cors: { origin: "*", }, }); io.on("connection", (socket) => { console.log("A user connected", socket.id); // HERE socket.on("client-ready", (data) => { console.log("client-ready", data); socket.emit("server-ready", "hey do you see this message?"); }); }); server.listen(3001, () => { console.log("Server is running on port 3001"); });
Emit on button click and then server will emit back to all clients
if we do socket.emit then it will only for the client that clicked the button
but if we do io.emit then it will be for all the connected clients
// server/index.js io.on("connection", (socket) => { console.log("A user connected", socket.id); socket.on("client-ready", (data) => { console.log("client-ready", data); socket.emit("server-ready", "hey do you see this message?"); }); socket.on("click", () => { io.emit("sse", "Kar liye maje? 😊"); console.log("hua hai button click, mujhe jaane do"); }); });
// app/page.tsx export default function Home() { useEffect(() => { socket.on("sse", (data) => { console.log("server data", data); }); }, []); return ( <main> <h1>Hello from Next.js</h1> <button onClick={() => socket.emit("click", "Button was clicked")}> Send message </button> </main> ); }