Theory is great, but building something practical is the best way to learn. Let's use the Socket.IO concepts of events and broadcasting to create two common real-time features: a group chat and a site-wide notification system.
Example 1: A Simple Group Chat App
Our goal is to build a chat where any message sent by a user is instantly visible to all other connected users.
The Server (index.js)
We'll set up an Express server to serve our HTML file and a Socket.IO server to handle the chat messages.
JavaScript
// index.js
import express from 'express';
import { createServer } from 'http';
import { Server } from 'socket.io';
import path from 'path';
const app = express();
const httpServer = createServer(app);
const io = new Server(httpServer);
// Serve the HTML file
app.get('/', (req, res) => {
res.sendFile(path.resolve('index.html'));
});
io.on('connection', (socket) => {
console.log('A user connected');
// When the server receives a 'chatMessage' event...
socket.on('chatMessage', (msg) => {
console.log('message: ' + msg);
// ...it emits the message to ALL connected clients.
io.emit('chatMessage', msg);
});
socket.on('disconnect', () => {
console.log('User disconnected');
});
});
httpServer.listen(3000, () => {
console.log('Listening on *:3000');
});
Key logic: When a message is received from one client (socket.on), it's sent back out to every client (io.emit).
The Client (index.html)
This file contains the UI (a form and a list) and the client-side JavaScript to communicate with the server.
HTML
<!DOCTYPE html>
<html>
<head>
<title>Simple Chat</title>
<style> /* Basic styling */
body { margin: 0; padding-bottom: 3rem; font-family: sans-serif; }
#form { background: rgba(0,0,0,0.1); padding: 0.25rem; position: fixed; bottom: 0; left: 0; right: 0; display: flex; }
#input { border: none; padding: 0 1rem; flex-grow: 1; }
#messages { list-style-type: none; margin: 0; padding: 0; }
#messages > li { padding: 0.5rem 1rem; }
</style>
</head>
<body>
<ul id="messages"></ul>
<form id="form" action="">
<input id="input" autocomplete="off" /><button>Send</button>
</form>
<script src="/socket.io/socket.io.js"></script>
<script>
const socket = io();
const form = document.getElementById('form');
const input = document.getElementById('input');
const messages = document.getElementById('messages');
form.addEventListener('submit', (e) => {
e.preventDefault();
if (input.value) {
// Emit the message to the server
socket.emit('chatMessage', input.value);
input.value = '';
}
});
// When we receive a 'chatMessage' event from the server
socket.on('chatMessage', (msg) => {
const item = document.createElement('li');
item.textContent = msg;
messages.appendChild(item);
window.scrollTo(0, document.body.scrollHeight);
});
</script>
</body>
</html>
Example 2: A Real-Time Notification System
Imagine an admin publishes a new article and we want to show a notification banner to all currently active users on the site instantly.
The best way to do this is to trigger the notification from a standard HTTP endpoint. This separates concerns: your existing backend logic handles the action (publishing an article), and Socket.IO just handles the real-time delivery.
The Server (index.js additions)
We'll add an Express endpoint that anyone can call. In a real app, this would be a protected admin route.
JavaScript
// ... (keep all the previous server code) ...
// We need this to parse JSON bodies from POST requests
app.use(express.json());
// A simple API endpoint to trigger a notification
app.post('/api/notify', (req, res) => {
const { message } = req.body;
if (!message) {
return res.status(400).json({ error: 'Message is required.' });
}
// Use the main 'io' instance to emit to all clients
io.emit('new-notification', { text: message });
res.status(200).json({ status: 'Notification sent!' });
});
Now, you can send a POST request to /api/notify with a JSON body like { "message": "New post published!" }, and the server will broadcast it.
The Client (index.html additions)
The client just needs to listen for this new event and display the notification.
HTML
<body>
<div id="notification-banner" style="display:none; background: lightblue; padding: 1rem; text-align: center;"></div>
<script>
// ... (keep all the previous client script) ...
const notificationBanner = document.getElementById('notification-banner');
// Listen for the notification event
socket.on('new-notification', (notification) => {
notificationBanner.textContent = notification.text;
notificationBanner.style.display = 'block';
// Hide the banner after 5 seconds
setTimeout(() => {
notificationBanner.style.display = 'none';
}, 5000);
});
</script>
</body>
Now our application can handle both chat and site-wide real-time notifications!