Onyx is a production-ready MERN + Socket.io chat app where all messages are encrypted on the client before they ever leave your device. The server stores and relays only ciphertext β it never sees your plaintext.
- AES-256 encryption β all messages encrypted/decrypted in the browser via
crypto-js - Server stores only ciphertext; plaintext never hits the backend
- XSS protection on all rendered Markdown via
DOMPurify - Server-side API key proxying β Groq API key is never exposed to the client
| Type | Description |
|---|---|
| π Normal | Persistent β messages saved to MongoDB |
| π» Ghost | Zero-persistence β room + messages auto-purged when everyone leaves |
| π Couples | Hard cap of 2 participants for private one-on-one chats |
Type @cipher in any normal or couples room to invoke an in-room AI powered by Groq's LLaMA 3.3 70B. Chat context is decrypted locally before being sent β the server only proxies already-assembled plaintext and never persists it. Responses are only visible to you.
| Command | Effect |
|---|---|
@cipher summarize |
Summarize recent messages |
@cipher translate <lang> |
Translate recent messages into the specified language |
@cipher tone? |
Analyze the tone of the last message |
@cipher draft |
Generate 3 reply drafts (Professional / Friendly / Concise) |
@cipher <question> |
Ask anything about the conversation |
@cipher help |
Show all commands |
Cipher is disabled in Ghost rooms for maximum privacy.
- Read receipts β single tick (delivered) / double ticks (seen), with a "Seen by" tooltip showing each viewer and timestamp
- Typing indicators β multi-user aware, e.g. "Priya and Rahul are typingβ¦"
- Edit messages within a 20-minute window (encrypted in-flight)
- Delete for everyone β instantly removes from DB and all connected clients
- Markdown rendering β bold, inline code, code blocks, tables, blockquotes, lists
- File sharing β up to 50 MB, chunked binary transfer via WebSockets (no third-party storage)
- QR code invite β scan to auto-join a room with the password pre-filled
- Recently joined rooms β quick-rejoin list stored in
localStorage, auto-purged when rooms no longer exist
- Creator can permanently delete a room and all its messages for everyone
- Non-creator can send a deletion request; the creator can approve or reject it in real time
- Ghost rooms self-destruct automatically when the last participant leaves
- Dark / Light theme toggle, persisted in
localStorage - Couples theme β optional pink color palette for Couples rooms, toggled via a heart button in the header
- Interactive particle vortex on the login screen (scales down on mobile/low-memory devices)
- Animated security radar background on the room selection screen (orbit dots, matrix rain, scan lines β all GPU-accelerated, disabled on mobile for 60 fps)
- Spring-physics animations throughout: message bubbles, send button pop, toast bounce-in, system message expand
- Fully responsive β hamburger + slide-in sidebar drawer on mobile
- Custom scrollbar styling,
prefers-reduced-motionrespected everywhere
Client β React 19, Vite 7, Socket.io-client, crypto-js, Firebase Auth, marked, DOMPurify, react-qr-code
Server β Node.js, Express 5, Socket.io 4, Mongoose, Helmet, express-rate-limit
Services β MongoDB Atlas (storage), Firebase Auth (Google sign-in), Groq API (Cipher AI via LLaMA 3.3 70B)
Browser Server External
ββββββββββββββββββββββ ββββββββββββββββββββββββββ ββββββββββββββ
plaintext message receives ciphertext only
β β
βΌ β
AES-256 encrypt (crypto-js) β
β β
βββββ Socket.io ββββββββββββββββΊβββββ MongoDB Atlas (ciphertext)
β
@cipher command β
β β
βΌ β
decrypt context locally β
βββββ HTTP POST ββββββββββββββββΊβββββ Groq API (transient plaintext)
β (never stored)
- The VITE_SECRET_KEY used for AES encryption lives only in the browser environment. All participants in a room share the same key (set via env var).
- Cipher context is assembled and decrypted client-side; only the resulting plaintext prompt travels to the server proxy β it is never written to any database.
- File transfers are chunked (256 KB chunks) and relayed through the Socket.io server in RAM. No file data is ever written to disk or a database.
- Node.js β₯ 18
- MongoDB Atlas cluster (free tier works)
- Firebase project with Google Auth enabled
- Groq API key (free at console.groq.com)
git clone https://github.com/hrithik18k/chupchat.git
cd chupchatcd server && npm installCreate server/.env:
PORT=5000
MONGO_URI=your_mongodb_connection_string
GROQ_API_KEY=your_groq_api_keynpm run devcd client && npm installCreate client/.env:
VITE_SECRET_KEY=any_long_random_string
VITE_FIREBASE_API_KEY=...
VITE_FIREBASE_AUTH_DOMAIN=...
VITE_FIREBASE_PROJECT_ID=...
VITE_FIREBASE_STORAGE_BUCKET=...
VITE_FIREBASE_MESSAGING_SENDER_ID=...
VITE_FIREBASE_APP_ID=...npm run devApp runs at http://localhost:5173 β both server and client must be running.
Note: All room participants must use the same
VITE_SECRET_KEYto decrypt each other's messages. In production, this key is baked into the deployed client bundle.
chupchat/
βββ client/
β βββ public/
β β βββ onyx-logo.png
β βββ src/
β βββ components/
β β βββ ChatRoom.jsx # Core chat UI, all socket event handlers, file transfer
β β βββ login.jsx # Google + Guest auth screen
β β βββ ParticleCanvas.jsx # Reusable canvas particle system (full / ambient variants)
β βββ utils/
β β βββ cipher.js # @cipher command parser, prompt builder, Groq proxy client
β βββ firebase.jsx # Firebase init + Google sign-in helper
β βββ App.jsx # Root: theme state, mouse-follower gradient, routing
β βββ App.css # Full design system, animations, responsive rules
β βββ index.css # Base resets
β
βββ server/
βββ models/
β βββ Message.js # Encrypted message schema (roomCode, sender, encryptedMessage, seenBy)
β βββ room.js # Room schema (code, password, roomType, users[], createdByName)
βββ index.js # Express app, Socket.io handlers, Cipher proxy, file relay
| Method | Route | Description |
|---|---|---|
GET |
/ |
Health check |
POST |
/api/cipher |
Proxy to Groq. Body: { systemPrompt, messages[] }. Rate-limited: 10 req/min per IP. |
GET |
/api/cipher/messages/:roomCode |
Last 20 encrypted messages for client-side Cipher context assembly |
| Event | Payload | Description |
|---|---|---|
create-room |
{ roomCode, user, password, roomType } |
Create a new room |
join-room |
{ roomCode, user, password } |
Join an existing room |
leave-room |
{ roomCode, user } |
Leave gracefully |
send-message |
{ roomCode, encryptedMessage, sender, timestamp } |
Broadcast a message |
edit-message |
{ roomCode, messageId, newEncryptedMessage, userName } |
Edit within 20-min window |
delete-message |
{ roomCode, messageId, userName } |
Delete for everyone |
typing / stop-typing |
{ roomCode, user } |
Typing indicator control |
mark-seen |
{ roomCode, messageIds[], userName } |
Update read receipts |
file-transfer-start |
{ transferId, roomCode, sender, fileName, fileType, fileSize, totalChunks } |
Begin chunked file transfer |
file-chunk |
{ transferId, roomCode, chunkIndex, chunk } |
Send a 256 KB base64 chunk |
delete-room |
{ roomCode, userName } |
Creator deletes the room |
request-delete-room |
{ roomCode, requesterName } |
Non-creator requests deletion |
approve-delete-room |
{ roomCode, userName } |
Creator approves deletion request |
reject-delete-room |
{ roomCode, requesterName } |
Creator rejects deletion request |
verify-recent-rooms |
{ roomCodes[] } |
Check which recent rooms still exist |
- Google Sign-In via Firebase OAuth popup
- Guest Mode β generates an anonymous
Guest####identity stored inlocalStorage; no account needed
- File transfer RAM β files are buffered in server RAM during relay. The free-tier Render instance (512 MB) may struggle with multiple concurrent large file transfers.
- Shared encryption key β AES-256 is symmetric; all room participants share the key embedded in the client build. This protects data at rest and in transit from the server, but participants themselves can decrypt all messages by design.
- No message pagination β all past messages for a room are fetched on join. Large rooms with many messages may have slower load times.
- Fork β create branch β commit β PR against
main - Commit format:
feat: add voice messages,fix: ghost room cleanup
Open source. See LICENSE for details.