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!