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’s frontend is a React 18 single-page application built with Vite. Global state is split across two React context providers — one for authentication, one for the live socket connection — and a single Zustand store that tracks the active conversation and its messages. Every network call and socket subscription is encapsulated in a custom hook, keeping components thin and easy to reason about. Tailwind CSS and DaisyUI handle styling, while react-hot-toast surfaces transient feedback without cluttering component state.

Source Directory Structure

frontend/src/
├── pages/
│   ├── home/          # Home page (auth-guarded)
│   ├── login/         # Login page
│   └── signup/        # Sign-up page
├── components/
│   ├── sidebar/       # Sidebar, SearchInput, Conversations, LogoutButton
│   └── messages/      # MessageContainer, Messages, MessageInput
├── hooks/             # Custom data-fetching and socket hooks
├── context/
│   ├── AuthContext.jsx
│   └── SocketContext.jsx
├── zustand/
│   └── useConversation.js
└── utils/             # Shared helpers (e.g. extractTime)

Routing

React Router v6 powers client-side navigation. There are three routes, and the root route is guarded by the presence of authUser from AuthContext.
<Routes>
  <Route path="/"        element={authUser ? <Home />  : <Navigate to="/login" />} />
  <Route path="/login"   element={authUser ? <Navigate to="/" /> : <Login />} />
  <Route path="/signup"  element={authUser ? <Navigate to="/" /> : <SignUp />} />
</Routes>
Authenticated users are redirected away from /login and /signup automatically. Unauthenticated users who try to reach / are sent to /login.

State Management

Chat App composes three independent state primitives, each suited to a different concern.

AuthContext

AuthContextProvider wraps the entire application and exposes { authUser, setAuthUser }. Initial state is hydrated from localStorage under the key chat-user, so sessions survive a page refresh without an extra round-trip to the server.
const [authUser, setAuthUser] = useState(
  JSON.parse(localStorage.getItem("chat-user")) || null
);
Any hook or component that calls useAuthContext() receives the current user object and a setter. Hooks like useLogin and useLogout call setAuthUser (and update localStorage) after a successful API response.

SocketContext

SocketContextProvider watches authUser via a useEffect. When a user logs in, it opens a socket.io-client connection and passes userId as a handshake query parameter so the server can map the user to their socket ID.
useEffect(() => {
  if (authUser) {
    const socket = io("https://chat-app-yt.onrender.com", {
      query: { userId: authUser._id },
    });
    setSocket(socket);
    socket.on("getOnlineUsers", (users) => setOnlineUsers(users));
    return () => socket.close();
  } else {
    if (socket) { socket.close(); setSocket(null); }
  }
}, [authUser]);
The provider exposes { socket, onlineUsers }. When authUser becomes null (logout), the effect’s cleanup function closes the socket immediately.

useConversation (Zustand)

The Zustand store is the single source of truth for whichever conversation is currently open in the message pane.
const useConversation = create((set) => ({
  selectedConversation: null,
  setSelectedConversation: (selectedConversation) => set({ selectedConversation }),
  messages: [],
  setMessages: (messages) => set({ messages }),
}));
FieldTypePurpose
selectedConversationobject | nullThe user object of the person being chatted with
setSelectedConversationfunctionUpdates the active conversation; triggers message fetch
messagesarrayAll messages for the selected conversation
setMessagesfunctionReplaces or appends to the message list
Because Zustand stores are module-level singletons, any component or hook can call useConversation() without prop drilling or an extra context provider.

Custom Hooks

All data-fetching, mutation, and socket-subscription logic lives in dedicated hooks under src/hooks/.
HookDescription
useSignupPOSTs to /api/auth/signup, sets authUser on success
useLoginPOSTs to /api/auth/login, sets authUser on success
useLogoutPOSTs to /api/auth/logout, clears authUser and localStorage
useSendMessagePOSTs a new message to /api/messages/:id, appends it to the Zustand store
useGetMessagesGETs the message history for selectedConversation from /api/messages/:id
useGetConversationsGETs the full contact list from /api/users for the sidebar
useListenMessagesSubscribes to the newMessage socket event and appends incoming messages to the Zustand store
useListenMessages is mounted inside MessageContainer so it only subscribes while a conversation is open, avoiding duplicate event handlers.

Component Structure

The Home page composes two top-level components side by side. Sidebar
  • SearchInput — filters the contact list by name in real time
  • Conversations — renders one Conversation item per contact returned by useGetConversations; highlights contacts that appear in onlineUsers
  • LogoutButton — calls useLogout and clears session state
MessageContainer
  • Messages — maps over messages from the Zustand store and renders each bubble with timestamp
  • MessageInput — controlled input that calls useSendMessage on submit

UI Stack

LibraryVersionPurpose
Tailwind CSS^3.4.1Utility-first CSS; layout, spacing, and colour
DaisyUI^4.6.1Tailwind component library; buttons, inputs, avatars, chat bubbles
react-icons^5.0.1Icon set used for send button, search, and logout
react-hot-toast^2.4.1Non-blocking toast notifications for errors and confirmations
DaisyUI is a devDependency — its classes are purged by Tailwind’s content scanner at build time, so no DaisyUI JavaScript ships to the browser.

Build docs developers (and LLMs) love