A full-stack real-time chat application built with Node.js, Express, Socket.IO, and React.
- Overview
- Architecture
- Project Structure
- Component Interaction
- Data Flow
- Environment Setup
- Running Locally
- Deployment
- API Reference
- Contributing
- Code of Conduct
Neomon is a real-time web chat application that allows users to join rooms, send messages, and communicate instantly with others. The project is structured as a monorepo containing two packages:
| Package | Description |
|---|---|
backend/ |
Node.js + Express REST API and Socket.IO server |
neomon/ |
React-based frontend client |
Neomon follows a classic client-server architecture with WebSocket support layered on top of HTTP.
┌────────────────────────────────────────────────────┐
│ CLIENT (Browser) │
│ │
│ ┌─────────────────────────────────────────────┐ │
│ │ React Application (neomon/) │ │
│ │ │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ Pages │ │Components│ │ Context │ │ │
│ │ │ (Routes) │ │ (UI) │ │ (State) │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ │ │
│ │ │ │ │
│ │ Socket.IO Client SDK │ │
│ └────────────────────┼────────────────────────┘ │
└───────────────────────┼────────────────────────────┘
│ WebSocket / HTTP
┌───────────────────────┼────────────────────────────┐
│ SERVER │
│ │
│ ┌─────────────────────────────────────────────┐ │
│ │ Node.js + Express (backend/) │ │
│ │ │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ Routes │ │ Socket │ │Middleware│ │ │
│ │ │ (REST) │ │ Handlers │ │(Auth etc)│ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ │ │
│ │ │ │
│ └─────────────────────────────────────────────┘ │
│ │ │
│ ┌────────────────┐ │
│ │ Database │ │
│ │ (MongoDB/other)│ │
│ └────────────────┘ │
└────────────────────────────────────────────────────┘
- WebSockets via Socket.IO: Enables low-latency, bidirectional communication for live messaging without polling.
- React Frontend: Component-driven UI with local state management, re-rendering only changed parts of the DOM.
- Monorepo Layout: Backend and frontend are co-located in one repository with a root-level
package.jsonto coordinate scripts. - REST + WS Hybrid: HTTP REST is used for authentication and data fetching; WebSockets handle the live message bus.
Neomon---Chat-Application/
├── package.json # Root-level scripts (run both services)
├── .gitignore
│
├── backend/ # Node.js / Express server
│ ├── package.json
│ ├── server.js # Entry point — Express app + Socket.IO setup
│ ├── config/
│ │ └── db.js # Database connection
│ ├── models/
│ │ ├── User.js # User schema/model
│ │ └── Message.js # Message schema/model
│ ├── routes/
│ │ ├── auth.js # Authentication routes (register/login)
│ │ └── messages.js # Message history routes
│ ├── middleware/
│ │ └── auth.js # JWT verification middleware
│ └── socket/
│ └── handlers.js # Socket.IO event handlers
│
└── neomon/ # React frontend
├── package.json
├── public/
│ └── index.html
└── src/
├── index.js # React entry point
├── App.js # Root component & routing
├── context/
│ └── SocketContext.js # Socket.IO client context provider
├── pages/
│ ├── Login.js # Login/Register page
│ └── Chat.js # Main chat page
└── components/
├── MessageList.js # Renders message history
├── MessageInput.js# Input box & send button
└── UserList.js # Online users sidebar
App.js
├── SocketContext (Provider) ← wraps the whole app, holds socket instance
│
├── /login → Login.js ← handles credentials, calls REST API
│
└── /chat → Chat.js ← main view
├── UserList.js ← listens to "users" socket events
├── MessageList.js ← listens to "message" socket events
└── MessageInput.js ← emits "sendMessage" socket events
SocketContext (src/context/SocketContext.js) is the central hub for WebSocket communication. It:
- Creates and stores the Socket.IO client connection on mount.
- Passes the
socketinstance down to all child components via React Context. - Handles cleanup on unmount (disconnect).
| Module | Responsibility |
|---|---|
server.js |
Initialises Express, attaches Socket.IO, starts HTTP listener |
config/db.js |
Opens database connection at startup |
routes/auth.js |
POST /api/auth/register and POST /api/auth/login |
routes/messages.js |
GET /api/messages/:roomId — fetch message history |
middleware/auth.js |
Verifies JWT token on protected routes |
socket/handlers.js |
Handles join, sendMessage, disconnect events |
Browser Backend
│ │
│── POST /api/auth/login ──>│
│ │── validate credentials
│ │── generate JWT
│<── { token, user } ──────│
│ │
│ (store token in memory) │
Browser (Socket.IO client) Backend (Socket.IO server)
│ │
│── connect (with JWT in handshake) ─>│
│ │── verify token
│── emit("join", { room }) ─────────>│
│ │── socket.join(room)
│<── emit("roomHistory", messages) ──│
│<── broadcast("userJoined", user) ──│ (to others in room)
Browser Backend Database
│ │ │
│── emit("sendMessage", msg) ───>│ │
│ │── save Message ──────────>│
│ │<── saved doc ─────────────│
│<── broadcast("message", msg) ──│ (to all in room)
Browser Backend
│ │
│── (tab closed / navigate away) │
│── socket disconnect ──────────>│
│ │── socket.leave(room)
│ │── broadcast("userLeft", user)
| Tool | Version |
|---|---|
| Node.js | ≥ 18.x |
| npm | ≥ 9.x |
| MongoDB | ≥ 6.x (local or Atlas) |
| Git | Any recent version |
git clone https://github.com/bhanupratapvk06/Neomon---Chat-Application.git
cd Neomon---Chat-ApplicationInstall all packages from the root (or each directory individually):
# Root dev dependencies (if any)
npm install
# Backend
cd backend && npm install && cd ..
# Frontend
cd neomon && npm install && cd ..Backend — create backend/.env:
# Server
PORT=5000
NODE_ENV=development
# Database
MONGO_URI=mongodb://localhost:27017/neomon
# Auth
JWT_SECRET=your_super_secret_key_here
JWT_EXPIRES_IN=7d
# CORS
CLIENT_URL=http://localhost:3000Frontend — create neomon/.env:
REACT_APP_API_URL=http://localhost:5000
REACT_APP_SOCKET_URL=http://localhost:5000
⚠️ Never commit.envfiles. They are listed in.gitignore.
npm run devThis uses a tool like
concurrentlyto boot the backend and frontend in parallel.
# Terminal 1 — Backend (port 5000)
cd backend
npm run dev # uses nodemon for hot-reload
# Terminal 2 — Frontend (port 3000)
cd neomon
npm startOpen http://localhost:3000 in your browser.
- Push your repo to GitHub (already done).
- Connect the repo to Vercel or Netlify.
- Set the root directory to
neomonand the build command tonpm run build. - Add your environment variables (
REACT_APP_API_URL,REACT_APP_SOCKET_URL) in the dashboard.
- Connect your repo to Railway or Render.
- Set the root directory to
backend. - Set the start command to
node server.js. - Add all environment variables from
backend/.env. - Provision a MongoDB instance (MongoDB Atlas is recommended for production).
| Variable | Description |
|---|---|
PORT |
Port the server listens on (set automatically by most platforms) |
MONGO_URI |
MongoDB connection string |
JWT_SECRET |
Secret for signing tokens — use a long, random string |
CLIENT_URL |
Deployed frontend URL (for CORS allowlist) |
NODE_ENV |
Set to production |
# backend/Dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 5000
CMD ["node", "server.js"]docker build -t neomon-backend ./backend
docker run -p 5000:5000 --env-file backend/.env neomon-backend| Method | Endpoint | Body | Description |
|---|---|---|---|
POST |
/api/auth/register |
{ name, email, password } |
Register a new user |
POST |
/api/auth/login |
{ email, password } |
Login and receive JWT |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET |
/api/messages/:roomId |
✅ JWT | Fetch message history for a room |
Client → Server
| Event | Payload | Description |
|---|---|---|
join |
{ room, user } |
Join a chat room |
sendMessage |
{ room, message, user } |
Send a message to a room |
disconnect |
— | Automatically fired on client disconnect |
Server → Client
| Event | Payload | Description |
|---|---|---|
roomHistory |
Message[] |
Past messages on room join |
message |
Message |
New message broadcast |
userJoined |
User |
Notifies room a user joined |
userLeft |
User |
Notifies room a user left |
onlineUsers |
User[] |
Current list of online users |
Contributions are very welcome! Here's how to get started:
# Fork on GitHub, then:
git clone https://github.com/YOUR_USERNAME/Neomon---Chat-Application.git
cd Neomon---Chat-Applicationgit checkout -b feat/your-feature-name
# or for fixes:
git checkout -b fix/issue-descriptionBranch naming conventions:
feat/— new featuresfix/— bug fixesdocs/— documentation updatesrefactor/— code refactoringtest/— adding or updating tests
- Keep commits small and focused.
- Write clear commit messages following Conventional Commits:
feat: add typing indicator to chat rooms fix: resolve socket disconnect on page refresh docs: update environment variable examples
# Run linting
cd backend && npm run lint
cd neomon && npm run lint
# Run tests (if available)
npm testgit push origin feat/your-feature-nameThen open a Pull Request on GitHub against the main branch. In your PR description:
- Explain what you changed and why.
- Reference any related issues using
Closes #<issue-number>. - Add screenshots for UI changes.
A maintainer will review your PR. Be responsive to feedback — we aim to review within a few days.
- 🐛 Bug fixes
- ✨ New features (open an issue first to discuss)
- 📝 Documentation improvements
- ♻️ Refactoring and performance improvements
- 🧪 Tests
- Large, unscoped PRs that touch everything at once
- Breaking changes without prior discussion in an issue
- Committing
.envfiles or secrets
This project follows the Contributor Covenant Code of Conduct. By participating, you agree to uphold a welcoming and respectful environment for everyone.
This project is licensed under the MIT License — see the LICENSE file for details.