Skip to content

Musheer0/ws-chat-app-basic

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 

Repository files navigation

🚀 Super Simple Chat App

A real-time chat application built with raw WebSockets, custom authentication, and a full-stack architecture using Next.js, Express, PostgreSQL, Redis, Docker, and TanStack React Query.

This project was built to deeply understand:

  • How WebSockets actually work (no Socket.io magic)
  • How authentication works from scratch
  • How sessions and caching behave in real systems
  • How state syncing works between REST + WebSocket
  • How real-time apps are structured in production

🧠 Core Idea

No Firebase. No third-party auth. No “chat SDK”.

Just:

  • Raw WebSocket server
  • Custom session-based auth (7-hour expiry)
  • PostgreSQL for persistence
  • Redis for caching
  • In-memory tracking for live members
  • TanStack React Query for client data synchronization
  • Docker for environment isolation

🏗️ Architecture

Client (Next.js)
   ↓ REST (initial data)
Backend (Express)
   ↓ WebSocket (real-time events)
In-memory presence layer
   ↓
Redis (caching layer)
   ↓
PostgreSQL (source of truth)

⚙️ Tech Stack

Frontend

  • Next.js (App Router)
  • TanStack React Query
  • Zustand
  • WebSocket API (native browser API)

Backend

  • Express
  • ws (raw WebSocket library)
  • Prisma ORM
  • PostgreSQL
  • Redis

DevOps

  • Docker
  • pnpm workspace

🔐 Authentication System (Custom Built)

JWT+SESSION IN DB.

Sessions are stored in PostgreSQL and validated on:

  • REST requests (via middleware)
  • WebSocket connection handshake

How it works:

  1. User signs in
  2. Session is created in DB
  3. Cookie stores session ID
  4. Middleware verifies session
  5. WebSocket validates session during connection

Sessions expire after 7 hours.

If expired:

  • User is locked out
  • Must re-authenticate

⚡ Real-Time Layer (Raw WebSocket)

Built using ws.

WebSocket handles:

  • New message broadcasting
  • Typing indicators
  • Presence tracking
  • Chat updates
  • Member add/remove events

Presence Handling

Online members are stored in memory (because presence is temporary state).

Why not database?

Because:

  • Presence is ephemeral
  • Writing to DB for every connect/disconnect = unnecessary load
  • Memory is faster

🎯 Why This Project Exists

This project was built mainly to understand how WebSockets work at a low level.

Goals included:

Handling WebSocket connections manually (no Socket.io)

Authenticating users during the socket handshake

Broadcasting events across connected clients

Managing in-memory presence

Syncing REST data with real-time updates

The focus was not on scaling or production hardening, but on understanding the mechanics of real-time communication from scratch.


🧠 Data Strategy

PostgreSQL = Source of Truth

Stores:

  • Users
  • Chats
  • Messages
  • Sessions

Redis = Caching Layer

Used for:

  • Frequently accessed chat data
  • Reducing DB reads

React Query = Client State Sync

Handles:

  • Paginated chat messages
  • Optimistic updates
  • Cache invalidation
  • Background refetching

WebSocket events update the React Query cache manually.


📦 Project Structure

backend/
  ├── Express server
  ├── Prisma schema
  ├── REST routers
  ├── WebSocket server
  ├── Redis config
  └── Auth middleware

frontend/
  ├── Next.js app router
  ├── WebSocket provider
  ├── React Query provider
  ├── Zustand stores
  └── Feature-based structure

🔥 Features

  • User registration & login
  • Session-based authentication (7-hour expiry)
  • Create chats (private/group)
  • Add / remove members(not implemented in fr)
  • Rename chat (not implemented in fr)
  • Transfer chat ownership(not implemented in fr)
  • Close / reopen chats(not implemented in fr)
  • Send messages
  • Typing indicators
  • Paginated message loading
  • Optimistic UI updates

🧪 Why Raw WebSockets?

Because abstractions hide reality.

Using ws directly helped understand:

  • Handshake lifecycle
  • Connection state
  • Event broadcasting
  • Scaling limitations
  • Memory tracking
  • Authentication inside socket upgrade

No magic. Just protocol-level behavior.

🧩 Lessons Learned

  • WebSockets are stateful scaling them is not trivial
  • Presence tracking belongs in memory
  • React Query + WebSocket is powerful but requires manual cache syncing
  • Session-based auth is more controllable than JWT only for server-side systems
  • Caching strategy matters more than people think

🚀 Future Improvements

  • Horizontal scaling with Redis pub/sub for WebSocket sync
  • Rate limiting
  • Message reactions
  • Read receipts
  • E2E encryption
  • Load testing
  • CI/CD pipeline

🎯 Why This Project Matters

This is not a UI-heavy project.

This is a systems-understanding project.

It demonstrates:

  • Real-time architecture knowledge
  • Authentication design
  • State synchronization
  • Caching strategies
  • Backend + frontend integration

If you're reading this as a recruiter or developer:

This project wasn’t built to make a complete chat app It was built to understand how chat systems actually work under

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages