A real-time chat app — messaging, status stories, media sharing, reactions, and live typing/online indicators. Built with React, Node.js, Express, MongoDB, and Socket.io.
Not WhatsApp. Chatly is a personal portfolio project by Ansh Verma, not affiliated with WhatsApp Inc. or Meta. WhatsApp is named only to describe what this project imitates. Read Avoiding phishing flags before changing any branding.
Try it without signing up: click Continue as Guest on the login screen. Guest accounts are deleted automatically after 24 hours.
| Auth | Email or phone OTP, JWT session cookies, one-click guest login |
| Chat | Real-time messaging over Socket.io with delivery and read receipts |
| Media | Images and videos in chats and status, stored on Cloudinary |
| Status | Image, video, or text updates that expire after 24 hours |
| Live state | Online/last-seen status and typing indicators |
| Extras | Emoji reactions, dark mode, responsive layout |
| Performance | Route-level code splitting, memoised chat rows, lazy avatars, indexed queries |
Stack — Frontend: React (Vite), Zustand, Tailwind CSS, Framer Motion. Backend: Express, Mongoose, Socket.io, JWT, Multer, Cloudinary. OTP: Nodemailer (email) and Twilio Verify (SMS).
You need Node 18+, a MongoDB instance (local or Atlas), and a Cloudinary account. Twilio and Gmail are optional — they only power SMS and email OTP.
git clone https://github.com/Anshv784/chatly.git
cd chatlyCreate backend/.env:
PORT=8080
MONGO_URI=mongodb://127.0.0.1:27017/chatly
JWT_SECRET=your_super_secret_jwt_key
ACCESS_POINT=http://localhost:3000
# Media uploads
CLOUDINARY_CLOUD_NAME=
CLOUDINARY_API_KEY=
CLOUDINARY_API_SECRET=
# SMS OTP (optional)
TWILIO_ACCOUNT_SID=
TWILIO_AUTH_TOKEN=
TWILIO_SERVICE_SID=
# Email OTP (optional)
EMAIL_USER=your_gmail_address
EMAIL_PASS=your_gmail_app_passwordcd backend && npm install && npm run devCreate frontend/.env:
VITE_API_URL=http://localhost:8080cd frontend && npm install && npm run devThe app runs at http://localhost:3000.
backend/
├── controllers/ # Request handlers (auth, chat, status)
├── lib/ # DB and Cloudinary config
├── middlewares/ # Auth guards, Multer setup
├── models/ # Mongoose schemas
├── routes/ # API endpoints
├── services/ # Socket.io, Twilio, email
└── src/server.js # Entry point
frontend/src/
├── components/ # Layout, sidebar, loaders
├── pages/ # Login, Chat, Status, Settings
├── services/ # Axios API clients
├── store/ # Zustand stores
└── utils/ # Helpers
- CORS origin whitelist and JSON payload size limits.
httpOnlycookies withsameSite: "none"for cross-site auth.- Multer accepts only whitelisted image, video, audio, and document types.
- Logs never contain credentials or OTP codes.
- Guest sessions are rate limited per IP and self-delete after 24h via a MongoDB TTL index.
This project was repeatedly flagged as a phishing site and had domains banned. The cause was brand impersonation, not the code. Keep these rules if you fork or redeploy it.
What triggered it
- The OTP email impersonated WhatsApp — sent from a personal Gmail with
from: "whatsapp web", subject "Your Whatsapp Verification Code", signed "WhatsApp Web Security Team". A verification code sent under a brand you do not own is textbook phishing: recipients report it, Gmail flags the sender, Safe Browsing flags the domain, the registrar bans it. This was the main cause. - The favicon was hot-linked from
static.whatsapp.net— a login page serving the real brand's favicon from the brand's own CDN is a strong automated phishing signal. - The page used the WhatsApp name and logo as its own identity while collecting emails and sending login codes.
What the repo does now
- Its own name (
Chatly) and a neutral chat-bubble icon. WhatsApp survives only as descriptive text. - Every OTP email names the app and author, links the public source, and states it is a portfolio demo unaffiliated with WhatsApp Inc. or Meta — in both the HTML and plaintext parts.
- The disclaimer appears on the login screen, the empty chat state, and in Settings.
index.htmlcarries description and Open Graph metadata identifying the site as a portfolio demo.
If a domain is already banned
- The ban is on the domain, not the code — deploy to a fresh domain instead of waiting it out.
- Request review via Search Console → Security Issues, and the Safe Browsing report form.
- Rename the app in one place:
appNameinfrontend/src/utils/portfolio.jsplus the matchingAPP_NAMEinbackend/services/emailService.js. - Do not revert the email template. That is what got the domains banned.
Built by Ansh Verma — anshverma.tech · @Anshv784 · anshv784@gmail.com
Email is the fastest way to reach me.