- โจ Overview
- ๐ฅ Demo
- ๐ Features
- ๐ฅ๏ธ Tech Stack
- ๐ Project Structure
- โก Real-Time Architecture
- ๐ Auth Flow
- โ๏ธ Environment Variables
- ๐ Getting Started
- ๐ฏ Roadmap
- ๐ก Lessons Learned
- ๐ค Contributing
Pulse is a production-grade full-stack real-time chat app built on the MERN stack โ crafted to deliver fast, beautiful, and secure messaging experiences.
Unlike barebones chat demos, Pulse is built with a real architecture:
- Optimistic UI so messages feel instant
- Socket.IO for true bi-directional, event-driven communication
- Cloudinary for image hosting
- Arcjet for security middleware
- JWT + HTTP-only cookies for bulletproof auth
Whether you're learning full-stack dev or want a solid chat foundation to build on โ Pulse has you covered.
| Feature | Description |
|---|---|
| โก Real-time messaging | Powered by Socket.IO โ no refresh needed |
| ๐ Optimistic UI | Messages appear instantly before server confirms |
| ๐ผ๏ธ Image sharing | Send images with preview before you hit send |
| ๐ Auto-scroll | Chat always anchors to the latest message |
| ๐ Timestamps | Every message has human-readable time |
| Feature | Description |
|---|---|
| ๐ Secure Auth | JWT tokens stored in HTTP-only cookies |
| ๐ข Online Presence | See who's online in real-time |
| ๐ค Profile Picture | Upload and update your avatar via Cloudinary |
| ๐ Contacts List | Browse and start conversations easily |
| ๐ Recent Chats | Quick access to your active conversations |
| Feature | Description |
|---|---|
| โจ๏ธ Typing sounds | Satisfying keyboard clicks as you type |
| ๐ Notification sounds | Hear incoming messages |
| ๐ Toggle sounds | Turn effects on/off anytime |
| ๐๏ธ Smooth animations | Polished transitions throughout |
| Feature | Description |
|---|---|
| ๐ก Express REST API | Clean, modular route structure |
| ๐ MongoDB Atlas | Cloud-hosted database |
| โ๏ธ Cloudinary | Optimized image uploads & hosting |
| ๐ง Resend Emails | Welcome emails on signup |
| ๐ก๏ธ Arcjet | Rate limiting & security layer |
| ๐ Socket.IO | Full-duplex real-time events |
| Technology | Purpose |
|---|---|
| UI Library | |
| Global State Management | |
| Utility-first Styling | |
| Component Library | |
| HTTP Client | |
| Client-side Routing | |
| Icon Library |
| Technology | Purpose |
|---|---|
| Server Runtime | |
| Web Framework | |
| Database | |
| ODM | |
| Real-time Engine | |
| Authentication | |
| Image Hosting | |
| API Security |
๐ Pulse/
โ
โโโ ๐ฅ๏ธ frontend/
โ โโโ ๐งฉ components/ # Reusable UI components
โ โโโ ๐ช hooks/ # Custom React hooks
โ โโโ ๐ pages/ # Route-level page components
โ โโโ ๐๏ธ store/ # Zustand global state stores
โ โโโ ๐ ๏ธ lib/ # Utility functions & config
โ โโโ ๐จ assets/ # Images, sounds, static files
โ
โโโ โ๏ธ backend/
โ โโโ ๐ฎ controllers/ # Route handler logic
โ โโโ ๐ middleware/ # Auth, error, Arcjet middleware
โ โโโ ๐ models/ # Mongoose data schemas
โ โโโ ๐ฃ๏ธ routes/ # Express API routes
โ โโโ ๐ ๏ธ lib/ # DB connection, Cloudinary, utils
โ โโโ ๐ง emails/ # Resend email templates
โ โโโ ๐ socket/ # Socket.IO setup & events
โ
โโโ ๐ README.md
flowchart TD
A(["Signup / Login"])
B["JWT Generated โ HS256 Signed"]
C["HTTP-Only Cookie โ Sent to browser"]
D{"Protected Route request?"}
E["Auth Middleware โ Verify JWT from cookie"]
F["401 Unauthorized"]
G["Socket Handshake โ Token verified on connect"]
H(["Connected & Online"])
A --> B --> C --> D
D -- Yes --> E
D -- No --> H
E -- Valid --> G --> H
E -- Invalid --> F
Create a .env file in /backend:
# โโ Server โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
PORT=3000
CLIENT_URL=http://localhost:5173
# โโ Database โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
MONGODB_URI=mongodb+srv://<username>:<password>@cluster.mongodb.net/pulse
# โโ Auth โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
JWT_SECRET=your_super_secret_jwt_key_here
# โโ Cloudinary โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
CLOUDINARY_CLOUD_NAME=your_cloud_name
CLOUDINARY_API_KEY=your_api_key
CLOUDINARY_API_SECRET=your_api_secret
# โโ Email (Resend) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
RESEND_API_KEY=re_xxxxxxxxxxxxxxxxxxxx
EMAIL_FROM=hello@yourdomain.com
EMAIL_FROM_NAME=Pulse
# โโ Security (Arcjet) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
ARCJET_KEY=ajkey_xxxxxxxxxxxxxxxxxxxx๐ก Tip: Never commit your
.envfile. Add it to.gitignoreimmediately!
Make sure you have these installed:
node --version # v18+
npm --version # v9+You'll also need accounts for:
- MongoDB Atlas โ free tier works great
- Cloudinary โ free tier works great
- Resend โ for welcome emails
- Arcjet โ for security
git clone https://github.com/LovelySharma-dev/Pulse.git
cd Pulsecd backend
npm installCreate your .env file (see Environment Variables above), then:
npm run dev
# โ
Server running at http://localhost:3000Open a new terminal:
cd frontend
npm install
npm run dev
# โ
App running at http://localhost:5173Navigate to http://localhost:5173 and start chatting! ๐
What's coming next for Pulse ๐
- โจ๏ธ Typing Indicator โ See when someone is typing
- โ Read Receipts โ Know when your message is seen
- ๐ Emoji Picker โ React and express yourself
- ๐๏ธ Voice Messages โ Record and send audio
- ๐น Video Calling โ Face-to-face in the browser
- ๐ Push Notifications โ Never miss a message
- ๐ฅ Group Chats โ Bring everyone together
- ๐ Message Search โ Find any conversation instantly
- โฉ๏ธ Reply to Messages โ Thread-style replies
- โ๏ธ Edit / Delete Messages โ Because typos happen
- ๐ Dark & Light Themes โ Choose your vibe
๐ Want to help build any of these? Open a PR!
Building Pulse was a deep dive into real-world full-stack challenges. Here's what made it interesting:
โก Optimistic UI Updates Making messages appear instantly while the server processes them โ and gracefully rolling back on failure โ required careful state management with Zustand.
๐ Real-Time Synchronization Keeping socket events, REST state, and UI in sync without stale data or race conditions taught the importance of a single source of truth.
๐ Socket Lifecycle Management Connecting, disconnecting, and reconnecting sockets cleanly โ especially across auth boundaries โ is more nuanced than the docs suggest.
๐ผ๏ธ Image Upload Pipeline Handling file selection โ preview โ base64 encoding โ Cloudinary upload โ URL storage in MongoDB without blocking the UI.
๐ JWT + Cookie Auth Understanding why HTTP-only cookies beat localStorage for token storage, and how to propagate auth context to Socket.IO handshakes.
๐๏ธ Zustand State Design Structuring stores so that chat state, auth state, and socket state stay decoupled but reactive to each other.
๐ REST + WebSockets Together Knowing when to use a REST call vs. a socket event โ and why you often need both for the same action.
Contributions are what make open source awesome. Any contributions you make are genuinely appreciated.
- Fork the repository
- Create your feature branch:
git checkout -b feature/AmazingFeature - Commit your changes:
git commit -m 'Add some AmazingFeature' - Push to the branch:
git push origin feature/AmazingFeature - Open a Pull Request
Found a bug? Open an issue Have an idea? Start a discussion










