How to Build Real-Time Communication with Socket.IO and Node.js

By Guilherme Luiz Maia Pinto
Picture of the author
Published on
Socket.IO and Node.js Real-Time Banner

Real-time communication is a cornerstone of modern web apps. Features like live chat, collaborative editing, and instant notifications transform user experiences. This article explains sockets and shows how to enable real-time communication using Socket.IO and Node.js with a small TypeScript example.


What Is a Socket?

A socket is an endpoint for sending/receiving data over a network. It creates a bi‑directional channel between client and server. Unlike classic HTTP’s request–response, sockets keep a persistent connection so data can flow both ways without repeated requests.

Why sockets matter:

  • Reduced latency: once connected, data is pushed instantly
  • Scalability: efficient event‑driven communication
  • Interactivity: live notifications, chats, dashboards, multiplayer games, IoT

Setup (TypeScript + Node.js)

mkdir real-time-app
cd real-time-app
npm init -y

# Runtime deps
npm install express socket.io

# Dev deps (TypeScript + types)
npm install -D typescript ts-node-dev @types/node @types/express

Initialize TypeScript:

npx tsc --init --rootDir src --outDir dist --esModuleInterop --resolveJsonModule --module commonjs --target es2020

Add scripts to package.json:

{
  "scripts": {
    "dev": "ts-node-dev --respawn --transpile-only src/server.ts",
    "build": "tsc",
    "start": "node dist/server.js"
  }
}

Server (src/server.ts)

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, { cors: { origin: '*' } })

// Serve a simple client
app.use(express.static(path.join(__dirname, 'public')))

io.on('connection', (socket) => {
  console.log('connected:', socket.id)

  socket.on('chat:message', (text: string) => {
    io.emit('chat:message', { id: socket.id, text, ts: Date.now() })
  })

  socket.on('disconnect', () => console.log('disconnected:', socket.id))
})

const PORT = process.env.PORT || 3000
httpServer.listen(PORT, () => console.log(`Listening on http://localhost:${PORT}`))

Client (public/index.html)

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Socket.IO Chat</title>
    <style>
      body { font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif; margin: 2rem; }
      #messages { border: 1px solid #ddd; padding: 1rem; height: 240px; overflow-y: auto; }
      form { margin-top: 1rem; display: flex; gap: 0.5rem; }
      input { flex: 1; padding: 0.5rem; }
    </style>
  </head>
  <body>
    <h1>Real-time Chat</h1>
    <div id="messages"></div>
    <form id="form">
      <input id="input" placeholder="Type a message..." />
      <button type="submit">Send</button>
    </form>

    <script src="/socket.io/socket.io.js"></script>
    <script>
      const socket = io()
      const messages = document.getElementById('messages')
      const form = document.getElementById('form')
      const input = document.getElementById('input')

      function append(msg) {
        const div = document.createElement('div')
        div.textContent = msg
        messages.appendChild(div)
        messages.scrollTop = messages.scrollHeight
      }

      socket.on('connect', () => append(`Connected as ${socket.id}`))
      socket.on('chat:message', (payload) => {
        const when = new Date(payload.ts).toLocaleTimeString()
        append(`[${when}] ${payload.id}: ${payload.text}`)
      })

      form.addEventListener('submit', (e) => {
        e.preventDefault()
        const text = input.value.trim()
        if (!text) return
        socket.emit('chat:message', text)
        input.value = ''
        input.focus()
      })
    </script>
  </body>
  </html>

Run It

npm run dev

Open two tabs at http://localhost:3000 and send messages: both tabs will update instantly.


Key Features of Socket.IO

  1. Event‑driven: custom events make communication intuitive
  2. Cross‑browser: provides fallbacks when WebSockets aren’t available
  3. Scalable: works with load balancers; supports adapters for clusters/Redis

Conclusion

Socket.IO with Node.js is a powerful combo for real‑time apps. You saw what sockets are, why they matter, and built a minimal chat to understand the flow. Extend this base to add auth, rooms, persistence, and horizontal scaling.

Stay Tuned

Want to become a Software Engineer pro?
The best articles and links related to web development are delivered once a week to your inbox.