Build a Real-Time Chat Application with Node.js
Lesson 9 of 10 90% of course

Bonus Features — Typing, Online Users & Timestamps

0 · 5 min · 6/7/2026

Learn Bonus Features — Typing, Online Users & Timestamps in our free Build a Real-Time Chat Application with Node.js series. Step-by-step explanations, examples, and interview tips on Toolliyo Academy.

Sign in to track progress and bookmarks.

Bonus Features — Typing, Online Users & Timestamps
Lesson 9 of 10 · Part 4 — Ship It · Build a Real-Time Chat Application with Node.js
Course: Build a Real-Time Chat Application with Node.js · Lesson: 9/10 · Read time: ~20 min · Level: Beginner

Bonus Features — Typing, Online Users & Timestamps

Good news: if you followed Lessons 3 and 6 exactly, these three features are already built in. This lesson explains each feature, the exact code involved, and how to extend them for homework assignments.

Feature 1 — Typing indicator

Shows “Alex is typing…” when someone presses keys in the message box.

Client change (client.js)

// Emit typing event on every input keystroke
messageInput.addEventListener('input', function () {
  socket.emit('typing');
});

// Listen for others typing
socket.on('user-typing', function (data) {
  if (data.username === currentUsername) return;
  typingIndicator.textContent = data.username + ' is typing…';
  typingIndicator.classList.remove('hidden');
  clearTimeout(typingTimeout);
  typingTimeout = setTimeout(function () {
    typingIndicator.classList.add('hidden');
  }, 1500);
});

Server change (server.js)

socket.on('typing', function () {
  socket.to(socket.room).emit('user-typing', {
    username: socket.username
  });
});

socket.to(room) excludes the typer — you do not need to see your own typing indicator.

💡 Tip: Debounce on the server too if traffic grows — for learning projects, client-side 1.5s hide timeout is enough.

Feature 2 — Online users list

Sidebar in chat header showing who is currently in the room.

Server — track users per room

const rooms = {}; // { general: ['Alice', 'Bob'], random: ['Charlie'] }

// On join-room:
if (!rooms[room]) rooms[room] = [];
if (!rooms[room].includes(username)) rooms[room].push(username);
io.to(room).emit('online-users', rooms[room]);

// On disconnect:
rooms[socket.room] = rooms[socket.room].filter(u => u !== socket.username);
io.to(socket.room).emit('online-users', rooms[socket.room] || []);

Client — render the list

socket.on('online-users', function (users) {
  renderOnlineUsers(users);
});

function renderOnlineUsers(users) {
  onlineUsersEl.innerHTML =
    '<strong>Online (' + users.length + ')</strong><span>' +
    users.join(', ') + '</span>';
}
⚠️ Common Mistake: Storing online users only on the client. Always treat the server as source of truth — clients can lie; server state after join/disconnect is authoritative.

Feature 3 — Message timestamps

Each chat bubble shows when the message was sent.

Server — attach ISO timestamp when broadcasting

io.to(socket.room).emit('receive-message', {
  type: 'chat',
  username: socket.username,
  message: message,
  timestamp: new Date().toISOString()  // e.g. 2026-05-28T14:30:00.000Z
});

Client — format for local timezone

function formatTime(isoString) {
  return new Date(isoString).toLocaleTimeString([], {
    hour: '2-digit',
    minute: '2-digit'
  });
}

// In bubble HTML:
'<div class="time">' + formatTime(data.timestamp) + '</div>'

toLocaleTimeString converts UTC ISO string to the user’s local time — 2:30 PM in India, 10:00 AM in London, automatically.

👨‍🏫 Teaching note: Homework ideas: (1) Add message character limit 500, (2) Show date separator “Today / Yesterday”, (3) Add emoji picker button, (4) Persist last 50 messages to a JSON file on server.

Homework extensions (optional challenges)

ChallengeHint
Private messagesEmit to specific socket.id instead of room
Message historyStore array in server memory; send on join
User colorsHash username → consistent bubble color
Profanity filterReplace bad words on server before broadcast

Verify all three features

  1. Two tabs, same room — online count shows 2
  2. Type without sending — other tab sees typing text
  3. Send message — time appears under bubble

Next lesson: put your chat on the internet with Railway free hosting.

Continue learning

Previous: How Socket.IO Works — Deep Dive

Next: Deploy to Railway, Troubleshooting & Summary

Course home: All 10 lessons

Test your knowledge

Quizzes linked to this course—pass to earn certificates.

Browse all quizzes
Build a Real-Time Chat Application with Node.js

On this page

Feature 1 — Typing indicator Client change (client.js) Server change (server.js) Feature 2 — Online users list Server — track users per room Client — render the list Feature 3 — Message timestamps Server — attach ISO timestamp when broadcasting Client — format for local timezone Homework extensions (optional challenges) Verify all three features Continue learning
Part 1 — Getting Started
Introduction — What We Are Building Project Setup — Folder, npm & Dependencies
Part 2 — Build the App
Building the Server — Express & Socket.IO Frontend HTML — Login Screen & Chat Layout Frontend CSS — Modern Chat UI Design Frontend JavaScript — Connect & Send Messages
Part 3 — Run, Learn & Extend
Running the App & Testing in Two Tabs How Socket.IO Works — Deep Dive
Part 4 — Ship It
Bonus Features — Typing, Online Users & Timestamps Deploy to Railway, Troubleshooting & Summary
Toolliyo Assistant
Ask about tutorials, ebooks, training, pricing, mentor services, and support. I use public site content only—not admin or internal tools.

care@toolliyo.com

Need callback? Share your details