Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/khushboodaryani/Chat-App/llms.txt

Use this file to discover all available pages before exploring further.

Chat App displays a live green dot next to every contact who is currently online. Presence state is maintained entirely through Socket.io connection and disconnection events — there is no polling, no heartbeat interval, and no additional database writes. The moment a user opens the app their presence is broadcast to every other connected client, and it disappears the instant they close their tab or lose connectivity.

How Presence Tracking Works

Server-side: userSocketMap

The server keeps a plain JavaScript object that maps each online user’s _id to their current Socket.io socket ID:
// backend/socket/socket.js
const userSocketMap = {}; // { userId: socketId }

io.on("connection", (socket) => {
  const userId = socket.handshake.query.userId;

  // Register the connection
  if (userId != "undefined") userSocketMap[userId] = socket.id;

  // Broadcast the updated online list to every connected client
  io.emit("getOnlineUsers", Object.keys(userSocketMap));

  socket.on("disconnect", () => {
    // Remove the user from the map
    delete userSocketMap[userId];

    // Broadcast the updated list again
    io.emit("getOnlineUsers", Object.keys(userSocketMap));
  });
});
Two events drive all presence updates:
TriggerAction
Socket connectionStore userId → socketId in userSocketMap; broadcast all keys
Socket disconnectDelete userId from userSocketMap; broadcast all keys

Client-side: SocketContext stores onlineUsers

The SocketContextProvider listens for the getOnlineUsers event and stores the received array in local state:
// frontend/src/context/SocketContext.jsx
socket.on("getOnlineUsers", (users) => {
  setOnlineUsers(users); // users is a string[] of user IDs
});
onlineUsers is then exposed to the entire component tree through context:
<SocketContext.Provider value={{ socket, onlineUsers }}>
  {children}
</SocketContext.Provider>

Reading Presence in Components

Any component can check whether a specific user is online with a single line:
const { onlineUsers } = useSocketContext();

const isOnline = onlineUsers.includes(userId);
The sidebar Conversations component uses this pattern to conditionally render a green indicator badge next to each contact:
const { onlineUsers } = useSocketContext();

// Inside the conversation list render:
{conversations.map((conversation) => {
  const isOnline = onlineUsers.includes(conversation._id);
  return (
    <div key={conversation._id} className="relative">
      <img src={conversation.profilePic} className="rounded-full w-12" />
      {isOnline && (
        <span className="absolute bottom-0 right-0 w-3 h-3 bg-green-500 rounded-full border-2 border-white" />
      )}
      <span>{conversation.fullName}</span>
    </div>
  );
})}
Because onlineUsers is a reactive state value inside a React context, the green dot appears and disappears automatically as users connect and disconnect — no manual refresh or polling required.

Presence Update Flow

1

User opens the app

SocketContextProvider detects a non-null authUser and opens a socket connection, passing userId in the query string.
2

Server registers the connection

The server’s connection handler stores userSocketMap[userId] = socket.id and calls io.emit("getOnlineUsers", Object.keys(userSocketMap)).
3

All clients update their sidebar

Every connected SocketContext receives the getOnlineUsers event and updates onlineUsers, causing the green dot to appear next to that user in every other user’s sidebar.
4

User closes the tab or logs out

The socket closes. The server’s disconnect handler fires, deletes the entry from userSocketMap, and broadcasts the updated list.
5

All clients remove the indicator

Each client receives the new onlineUsers array without that user’s ID, and the green dot disappears from every sidebar.

Ephemeral Nature of Presence Data

Presence state lives only in memory. userSocketMap is a plain JavaScript object in the server process — it is not written to MongoDB. If the server restarts (e.g. during a deploy or crash), the map is reset to an empty object. All clients must re-establish their socket connections before they reappear as online.For production deployments running multiple server instances, use the Socket.io Redis adapter so that userSocketMap is shared across all instances and presence data survives individual process restarts.

API Summary

useSocketContext()

Returns { socket, onlineUsers } from SocketContext. Call this in any component that needs to check or react to presence.

getOnlineUsers event

Emitted by the server to all clients whenever any user connects or disconnects. Payload is a string[] of currently online user IDs.

Build docs developers (and LLMs) love