Skip to content

wavey-waves/waves

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

140 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Waves - Real-time Chat Application

Waves is a modern, real-time chat application that offers global, network-based, and custom private chat rooms. Built with React, Node.js, and Socket.IO, it features a beautiful, responsive UI and seamless real-time communication.

Features

Three Room Types

  • Global Room: Connect with users worldwide in a public chat
  • Network Room: Auto-assigned rooms based on IP subnet for local connections
  • Custom Rooms: Private rooms with unique 6-character codes for secure sharing

Flexible Authentication

  • Anonymous login with auto-generated usernames and colors
  • Custom account creation with persistent identities
  • Room-specific color palettes for visual distinction

Advanced Messaging

  • Peer-to-Peer messaging via WebRTC with automatic server fallback
  • Real-time communication with message deduplication
  • Message reactions and timestamps

Responsive Design

  • Mobile-optimized interface with touch-friendly controls
  • Native sharing with clipboard fallback
  • Auto-focus input fields and rate limiting

Getting Started

Prerequisites

  • Node.js (v14 or higher)
  • MongoDB
  • npm or yarn

Installation

  1. Clone the repository
git clone https://github.com/wavey-waves/waves.git
cd waves
  1. Install dependencies for both frontend and backend
# Install backend dependencies
cd backend
npm install

# Install frontend dependencies
cd ../frontend
npm install
  1. Create environment files

Backend (.env):

PORT=3000
MONGODB_URI=your_mongodb_uri
JWT_SECRET=your_jwt_secret
NODE_ENV=development
  1. Start the development servers

Backend:

cd backend
npm run dev

Frontend:

cd frontend
npm run dev

Tech Stack

Frontend

  • React (Vite)
  • Socket.IO Client
  • Axios
  • TailwindCSS
  • React Router
  • react-toastify

Backend

  • Node.js
  • Express
  • Socket.IO
  • MongoDB with Mongoose
  • JWT Authentication

Complete System Flowchart

PLATFORM OVERVIEW

Waves is a real-time chat application featuring Peer-to-Peer (P2P) messaging with WebRTC Data Channels, automatic server fallback, and three room types: Global, Network-based, and Custom private rooms.

COMPLETE SYSTEM ARCHITECTURE

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                              WAVES CHAT PLATFORM                                β”‚
β”‚                          Real-time P2P Messaging System                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                        β”‚
                                        β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                               USER JOURNEY                                      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                        β”‚
                                        β–Ό
                        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                        β”‚                               β”‚
                        β–Ό                               β–Ό
            β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
            β”‚   ANONYMOUS USER    β”‚         β”‚ REGISTERED USER     β”‚
            β”‚   (localStorage)    β”‚         β”‚   (JWT Cookies)     β”‚
            β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                        β”‚                               β”‚
                        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                        β”‚
                                        β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                              ROOM SELECTION                                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                      β”‚
                 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                 β”‚                    β”‚                           β”‚
                 β–Ό                    β–Ό                           β–Ό
      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
      β”‚   GLOBAL ROOM       β”‚    β”‚ NETWORK        β”‚     β”‚ CUSTOM ROOM          β”‚
      β”‚   (/chat/global)    β”‚    β”‚ ROOM           β”‚     β”‚ (/chat/custom/XXXXXX)|
      β”‚                     β”‚    β”‚ (/chat/network)|     β”‚                      β”‚
      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                 β”‚                     β”‚                          β”‚
                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                       β”‚
                                       β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                            AUTHENTICATION FLOW                                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

AUTHENTICATION SYSTEM

Anonymous User Flow

1. User visits / (Home)
2. Clicks room type (Global/Network/Custom)
3. JoinRoom component loads
4. Check localStorage.getItem('anonymousUser')
   β”œβ”€β”€ If exists & valid (not expired):
   β”‚   └── Parse JSON: {name, color, expiry}
   β”‚       └── expiry = Date.now() + 7 days
   └── If missing/invalid/expired:
       └── Generate new random name & color
           β”œβ”€β”€ Name: unique-names-generator (adjective-color-animal)
           β”œβ”€β”€ Color: Room-specific color palette
           └── Store in localStorage as JSON

5. User clicks "Join as Anonymous"
6. POST /api/auth/login with {userName: randomName}
   β”œβ”€β”€ If user exists: Return user data
   └── If user doesn't exist: Auto-create via signup
       └── POST /api/auth/signup with {userName, color, isAnonymous: true}

7. Server generates JWT token (7 days expiry)
8. Cookie: jwt=token; httpOnly=true; secure=production; path="/"
9. Return: {_id, userName, color, isAnonymous: true}

Registered User Flow

1. User visits / (Home)
2. Clicks room type β†’ JoinRoom component
3. Selects "Create Account" tab
4. Enters username, password, selects color
5. POST /api/auth/signup with {userName, password, color, isAnonymous: false}
   β”œβ”€β”€ Validate: username unique, password β‰₯6 chars
   β”œβ”€β”€ Hash password: bcrypt.genSalt(10) + bcrypt.hash()
   β”œβ”€β”€ Store: {userName, hashedPassword, color, isAnonymous: false}
   └── Generate JWT token (7 days)

6. Cookie: jwt=token (same settings as anonymous)
7. Return: {_id, userName, color, isAnonymous: false}

Session Persistence

- JWT Cookie: 7 days expiry, httpOnly, secure in production
- Anonymous localStorage: 7 days expiry, auto-regenerates
- Color Assignment: Room-specific palettes (15 colors each)
  β”œβ”€β”€ Global: Purple/Violet/Blue theme
  β”œβ”€β”€ Network: Emerald/Cyan/Teal theme
  β”œβ”€β”€ Custom: Rose/Pink theme

ROOM TYPES & ASSIGNMENT

Global Room (/chat/global)

- Accessible to all authenticated users
- Room name: "global-room"
- No special assignment logic
- All users join same Socket.IO room: "global-room"

Network Room (/chat/network)

1. User authenticates successfully
2. POST /api/rooms/assign (protected route)
3. Extract client IP using request-ip package
4. Create subnet: IP.split('.').slice(0,3).join('.')
5. Generate roomName: `network-${subnet}`
6. Find/create room in MongoDB
   β”œβ”€β”€ If exists: Add user to members array
   └── If new: Create room with user as first member
7. Return: {roomId, roomName, memberCount, members[]}
8. Socket.IO join: socket.join(roomName)

Custom Room (/chat/custom/:code)

Creation Flow:
1. User clicks "Custom Room" on home
2. CustomRoom component loads
3. User clicks "Create Room"
4. POST /api/rooms/create
5. Generate unique 6-char code:
   β”œβ”€β”€ Loop until unique: Math.random().toString(36).substring(2,8).toUpperCase()
   β”œβ”€β”€ Check MongoDB: Room.findOne({code})
6. Create room: {roomName: `custom-${code}`, code, isCustomRoom: true}
7. Return: {roomId, roomName, code, memberCount: 0}

Joining Flow:
1. User enters URL: /chat/custom/ABC123
2. ChatRoute component loads
3. POST /api/rooms/join with {code: "ABC123"}
4. Find room by code (case-insensitive)
5. Return room info (without member details for privacy)
6. Show JoinRoom component for authentication
7. After auth: Join Socket.IO room by roomName

MESSAGING SYSTEM

Message Flow Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      MESSAGE SENDING FLOW                       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                β”‚
                                β–Ό
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚   User Types Message  β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                β”‚
                                β–Ό
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚   Input Validation    β”‚
                    β”‚   - Not empty         β”‚
                    β”‚   - ≀1000 chars       β”‚
                    β”‚   - Rate limit (1s)   β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                β”‚
                                β–Ό
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚   P2P Attempt First   β”‚
                    β”‚   (WebRTC DataChannel)β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                β”‚
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚           β”‚           β”‚
                    β–Ό           β–Ό           β–Ό
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚   P2P Success   β”‚  β”‚P2P  β”‚ β”‚  P2P Fails  β”‚
        β”‚   Direct Send   β”‚  β”‚Failsβ”‚ β”‚  Server     β”‚
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”˜ β”‚  Relay      β”‚
                                     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                             β”‚
                                             β–Ό
                                 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                                 β”‚   Server Processing                β”‚
                                 β”‚   POST /api/messages/send/:roomName|
                                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

WebRTC P2P Implementation

Connection Establishment:
1. User joins Socket.IO room
2. Server emits "existing-room-users" with other users
3. For each existing user:
   β”œβ”€β”€ Create RTCPeerConnection with ICE servers
   β”œβ”€β”€ Create DataChannel named "chat"
   β”œβ”€β”€ Create offer: pc.createOffer()
   β”œβ”€β”€ Set local description
   β”œβ”€β”€ Send offer via Socket.IO: "webrtc-offer"

4. Receiving user:
   β”œβ”€β”€ Create RTCPeerConnection
   β”œβ”€β”€ Set remote description (offer)
   β”œβ”€β”€ Create answer: pc.createAnswer()
   β”œβ”€β”€ Send answer via Socket.IO: "webrtc-answer"

5. ICE candidate exchange:
   β”œβ”€β”€ Both sides: pc.onicecandidate β†’ emit "webrtc-ice-candidate"
   β”œβ”€β”€ Add received candidates to peer connections

6. DataChannel setup:
   β”œβ”€β”€ dc.onopen: Connection ready for P2P messaging
   β”œβ”€β”€ dc.onmessage: Receive P2P messages
   β”œβ”€β”€ dc.onclose: Cleanup connection

Fallback Logic:
- If P2P fails after 10 seconds: Close connection, use server
- Network changes: Automatically attempt P2P reconnection
- Firewall/NAT issues: Seamless server relay fallback

Message Storage & Cleanup

Message Schema:
{
  senderId: ObjectId (ref: Users),
  room: String (default: "global-room"),
  text: String,
  reactions: [{
    userId: ObjectId,
    emoji: String,
    createdAt: Date
  }],
  expiresAt: Date (31 days for messages, 40 days for rooms)
}

Cleanup System:
- MongoDB TTL indexes auto-delete expired messages/rooms
- Manual cleanup: DELETE /api/messages/cleanup
  β”œβ”€β”€ Keep only latest 1000 messages per room
  β”œβ”€β”€ Delete older messages in batches
- Reaction limits: One reaction per user per message

UI/UX SYSTEM

Color Assignment System

Room-Based Color Palettes:

Global Room Colors (15 colors):
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ #8b5cf6 #a855f7 #6366f1 #3b82f6 #0ea5e9 #60a5fa β”‚
β”‚ #d946ef #ec4899 #f43f5e #f97316 #f59e0b #fbbf24 β”‚
β”‚ #eab308 #84cc16 #22c55e                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
Theme: Purple β†’ Violet β†’ Blue β†’ Indigo

Network Room Colors (15 colors):
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ #10b981 #14b8a6 #06b6d4 #34d399 #22c55e #84cc16 β”‚
β”‚ #0ea5e9 #60a5fa #3b82f6 #6366f1 #8b5cf6 #a855f7 β”‚
β”‚ #d946ef #ec4899 #f43f5e                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
Theme: Emerald β†’ Teal β†’ Cyan β†’ Green

Custom Room Colors (15 colors):
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ #f43f5e #ec4899 #d946ef #e11d48 #f97316 #fbbf24 β”‚
β”‚ #f59e0b #84cc16 #22c55e #10b981 #06b6d4 #3b82f6 β”‚
β”‚ #6366f1 #8b5cf6 #a855f7                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
Theme: Rose β†’ Pink β†’ Fuchsia

Responsive Design System

Mobile Optimizations:
- Viewport height: CSS custom property --vh
- Info button: Shows user details & room code on mobile
- Header layout: Logo acts as back button on mobile
- Touch-friendly: Larger buttons, swipe gestures
- Auto-focus: Input field focuses automatically on load

Desktop Features:
- Hover effects: Scale transforms, glow effects
- Gradient animations: CSS keyframe animations
- Modal dialogs: Documentation, room creation
- Native sharing: Web Share API with clipboard fallback

REAL-TIME COMMUNICATION

Socket.IO Event Flow

Server Events (io.on):
β”œβ”€β”€ "connection": New client connects
β”œβ”€β”€ "join": Client joins room
β”œβ”€β”€ "leave": Client leaves room
β”œβ”€β”€ "disconnect": Client disconnects
β”œβ”€β”€ "webrtc-offer": WebRTC offer received
β”œβ”€β”€ "webrtc-answer": WebRTC answer received
β”œβ”€β”€ "webrtc-ice-candidate": ICE candidate received

Client Events (socket.emit):
β”œβ”€β”€ "join": Join room
β”œβ”€β”€ "leave": Leave room
β”œβ”€β”€ "webrtc-offer": Send WebRTC offer
β”œβ”€β”€ "webrtc-answer": Send WebRTC answer
β”œβ”€β”€ "webrtc-ice-candidate": Send ICE candidate

Broadcast Events (io.to(room).emit):
β”œβ”€β”€ "userJoined": New user joined room
β”œβ”€β”€ "userLeft": User left/disconnected
β”œβ”€β”€ "chatMessage": New message received
β”œβ”€β”€ "message-reacted": Message reaction updated
β”œβ”€β”€ "existing-room-users": Send existing users to new joiner

Message Deduplication System

Processed Message IDs:
- Set<string> processedMessageIds (in-memory)
- Tracks both _id and tempId for each message
- Prevents duplicate rendering from P2P + Server paths
- Cleanup: Automatic garbage collection on component unmount

MOBILE OPTIMIZATION

Mobile UI Components

Info Button (Mobile Only):
- Position: Fixed top-right corner
- Content: Username, Room type/code, Member count
- Trigger: Click to show modal overlay
- Close: Click outside or X button

Header Layout:
- Desktop: Logo + Room info + Share + Info
- Mobile: Logo (back) + Room name + Info button
- Responsive breakpoints: Tailwind CSS classes

Input System:
- Auto-focus: textarea.focus() on component mount
- Auto-resize: Dynamic height based on content
- Character limit: 1000 chars with warning at 900
- Rate limiting: 1000ms throttle between sends

SHARING SYSTEM

Native Sharing Implementation

if (navigator.share) {
  // Web Share API (Mobile browsers)
  navigator.share({
    title: \`Join \${roomName}\`,
    text: \`Join my chat room: \${roomCode}\`,
    url: window.location.href
  });
} else {
  // Clipboard fallback (Desktop/some mobile)
  navigator.clipboard.writeText(window.location.href);
  toast.success("Room link copied to clipboard!");
}

URL Structure

/                    β†’ Home (room selection)
/chat/global         β†’ Global room
/chat/network        β†’ Network room (IP-based)
/chat/custom/:code   β†’ Custom room (code-based)

DATA PERSISTENCE

Cookies Stored

jwt: JWT token (7 days expiry)
β”œβ”€β”€ httpOnly: true (prevents XSS access)
β”œβ”€β”€ secure: true (HTTPS only in production)
β”œβ”€β”€ sameSite: "lax" (CSRF protection)
β”œβ”€β”€ path: "/" (available site-wide)

localStorage Items

anonymousUser: JSON string
β”œβ”€β”€ {name, color, expiry}
β”œβ”€β”€ expiry: Date.now() + 7 days
β”œβ”€β”€ Auto-regenerates when expired

Legacy keys (auto-migrated):
β”œβ”€β”€ anonymousUsername: string
β”œβ”€β”€ userColor: string

Database Collections

Users:
β”œβ”€β”€ _id, userName, password?, color, isAnonymous
β”œβ”€β”€ expiresAt (TTL: 7 days anonymous, 1 year registered)

Messages:
β”œβ”€β”€ senderId, room, text, reactions[], expiresAt
β”œβ”€β”€ TTL: 31 days

Rooms:
β”œβ”€β”€ roomName, code?, members[], createdByIp, isCustomRoom
β”œβ”€β”€ TTL: 40 days

DEPLOYMENT & CONFIGURATION

Environment Variables

Backend (.env):
β”œβ”€β”€ MONGODB_URI: MongoDB connection string
β”œβ”€β”€ PORT: Server port (default: 3000)
β”œβ”€β”€ JWT_SECRET: JWT signing key
β”œβ”€β”€ NODE_ENV: development/production

Frontend (.env.*):
β”œβ”€β”€ VITE_BACKEND_URL: API endpoint
    β”œβ”€β”€ Development: http://localhost:8000
    β”œβ”€β”€ Production: https://waves-c53a.onrender.com

Build Process

Root package.json scripts:
β”œβ”€β”€ build: Install deps + build frontend + install backend
β”œβ”€β”€ start: Start backend (serves built frontend)

Frontend (Vite):
β”œβ”€β”€ dev: Development server with HMR
β”œβ”€β”€ build: Production build to dist/
β”œβ”€β”€ preview: Preview production build

Backend (Node.js):
β”œβ”€β”€ dev: nodemon with auto-restart
β”œβ”€β”€ start: Production server

ERROR HANDLING & FALLBACKS

Connection Resilience

WebRTC P2P Fallback:
β”œβ”€β”€ Timeout: 10 seconds for P2P connection
β”œβ”€β”€ Auto-fallback: Server relay if P2P fails
β”œβ”€β”€ Reconnection: Automatic P2P reattempts

Network Issues:
β”œβ”€β”€ Socket.IO auto-reconnection
β”œβ”€β”€ Message queuing during disconnects
β”œβ”€β”€ Offline detection and user feedback

Authentication Errors:
β”œβ”€β”€ Token expiry: Redirect to join room
β”œβ”€β”€ Invalid token: Clear cookies, re-authenticate
β”œβ”€β”€ Network errors: Retry with exponential backoff

PERFORMANCE OPTIMIZATIONS

Message Cleanup

Automatic Cleanup:
β”œβ”€β”€ Keep latest 1000 messages per room
β”œβ”€β”€ Delete older messages in batches
β”œβ”€β”€ MongoDB TTL indexes for auto-expiry

Memory Management:
β”œβ”€β”€ Processed message ID deduplication
β”œβ”€β”€ Peer connection cleanup on disconnect
β”œβ”€β”€ Component unmount cleanup

Rate Limiting:
β”œβ”€β”€ 1000ms throttle between message sends
β”œβ”€β”€ Character limits (1000 max)
β”œβ”€β”€ Input validation before sending

USER EXPERIENCE FLOW

1. Landing Page
   β”œβ”€β”€ Animated "Waves" title with glow effects
   β”œβ”€β”€ Three room type cards with hover animations
   β”œβ”€β”€ Documentation button (top-right)
   └── Gradient background with subtle patterns

2. Room Selection
   β”œβ”€β”€ Global: Purple theme, instant access
   β”œβ”€β”€ Network: Green theme, IP-based auto-assignment
   β”œβ”€β”€ Custom: Pink theme, code generation/sharing

3. Authentication
   β”œβ”€β”€ Anonymous: Auto-generated name/color (localStorage)
   β”œβ”€β”€ Registered: Manual username/password creation
   β”œβ”€β”€ Color selection from room-specific palettes

4. Chat Interface
   β”œβ”€β”€ Real-time P2P messaging with server fallback
   β”œβ”€β”€ Mobile-responsive header with info modal
   β”œβ”€β”€ Auto-focus input field
   β”œβ”€β”€ Message reactions (one per user)
   β”œβ”€β”€ Share functionality with native API

5. Message Features
   β”œβ”€β”€ P2P priority with seamless server fallback
   β”œβ”€β”€ User color coding for message distinction
   β”œβ”€β”€ Timestamp display
   β”œβ”€β”€ Auto-scroll to latest messages
   β”œβ”€β”€ Character counter with warnings

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add some AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

Acknowledgments

About

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages