Skip to content

Repository files navigation

RealTimeBoard

A collaborative real-time application built as part of a structured portfolio-building program focused on production-grade engineering practices — moving beyond "it works" into understanding why it works.

This is Flagship Project 1 of 3, designed to build depth in WebSockets, concurrency, and real-time state synchronization.

Current Status: Milestone 3 — Real-Time Messaging Engine ✅ (Complete)

Milestone 1 proved a JWT could gate a live WebSocket connection. Milestone 2 added board creation and room-based joining with membership authorization. Milestone 3 builds the full collaborative core: a real-time chat engine with sending, editing, and deleting messages — including dual authorization, soft-delete, and paginated history retrieval.

What's built so far

Auth (REST)

  • User model with bcrypt password hashing via a Mongoose pre hook
  • Signup / login endpoints
  • Zod-based request validation middleware
  • Centralized error handling middleware
  • HTTP-side JWT verification middleware (separate from the socket-side version, since tokens are read from different locations)

Boards (REST)

  • Board model — owner reference + role-based membership array (owner / moderator / member)
  • Board passwords hashed via the same pre hook pattern used for users
  • createBoard endpoint — owner is automatically added to boardMembers at creation time
  • getMessages endpoint — paginated message history for a board, membership-gated, with soft-deleted messages sanitized (content stripped) before being sent to the client
  • Sensitive fields (hashed passwords) stripped from API responses

Messages (Real-time, Socket.io)

  • Message model — supports text, image, or both on a single message; optional reply-to reference; soft-delete fields (deleted, deletedBy, deletedAt) for a future recoverable-delete window
  • Custom schema-level validation ensuring a message always has text, an image, or both — never neither
  • sendMessage — verifies sender is an actual board member before persisting and broadcasting
  • editMessage — author-only, verified against the message's stored sender
  • deleteMessage — dual authorization: the original sender OR a board owner/moderator can delete; soft-deletes (marks deleted: true rather than removing the record) and broadcasts structured deletion data (deletedBy, isAdminDelete) so the frontend controls its own display logic
  • All real-time events scoped to io.to(boardId) — reaching only members of that specific board, never the whole server

Real-time infrastructure (Socket.io)

  • Socket.io wired onto a raw HTTP server (required for the WebSocket upgrade handshake)
  • io.use() middleware verifies a JWT at connection time, before a socket is accepted
  • Socket event logic lives in its own module (sockets/boardHandlers.js), keeping server.js focused purely on infrastructure wiring
  • joinBoard — skips password verification for existing members (e.g. reconnecting after a refresh); requires the correct board password for first-time joiners, then adds them as a member

Tech Stack

  • Node.js (ES Modules)
  • Express
  • Socket.io
  • MongoDB Atlas + Mongoose
  • JWT + bcrypt
  • Zod (validation)

Project Structure

config/       → Database connection
controllers/  → Auth and board logic
middleware/   → Error handling, validation, JWT verification (HTTP + socket)
models/       → Mongoose schemas (User, Board, Message)
routes/       → Express route definitions
sockets/      → Socket.io event handlers, registered onto io from server.js
validators/   → Zod schemas
server.js     → App entry point — Express, HTTP server, Socket.io wiring

Setup

npm install

Create a .env file:

PORT=3000
MONGO_URI=your_mongodb_atlas_connection_string
JWT_SECRET=your_secret_here

Run in development:

npm run dev

API Endpoints

Method Endpoint Description
POST /api/auth/register Create a new user
POST /api/auth/login Authenticate and receive a JWT
POST /api/boards/create-board Create a new board (requires Authorization: Bearer <token>)
GET /api/boards/:boardId/messages Fetch a board's message history, paginated (requires Authorization: Bearer <token>)

Message history pagination: the endpoint returns the 10 most recent messages by default. Pass ?before=<ISO timestamp> (the createdAt of the oldest message currently loaded) to fetch the next 10 older messages — anchored to a timestamp rather than a page number, so results stay accurate even as new messages arrive elsewhere in the room.

Socket Authentication

Clients must attach a valid JWT when connecting:

const socket = io("http://localhost:3000", {
  auth: { token: yourJWT }
});

Real-Time Events

Joining a board:

socket.emit("joinBoard", { boardId, boardPassword });

socket.on("joinSuccess", (data) => { /* now in the room */ });
socket.on("joinError", (data) => { /* not authorized, or board not found */ });

Sending a message:

socket.emit("sendMessage", { boardId, text, imageUrl, replyTo });

socket.on("newMessage", (data) => { /* broadcast to the whole room */ });
socket.on("boardError", (data) => { /* not a board member */ });

Editing a message (author only):

socket.emit("editMessage", { messageId, newText });

socket.on("messageEdited", (data) => { /* broadcast to the whole room */ });
socket.on("messageError", (data) => { /* not found, deleted, or not the author */ });

Deleting a message (author or board admin):

socket.emit("deleteMessage", { messageId });

socket.on("deletedMessage", (data) => { /* { messageId, deletedBy, isAdminDelete } */ });
socket.on("deleteError", (data) => { /* unauthorized */ });

Roadmap

  • Frontend (next): React + Vite client with Zustand for state management — auth pages, socket connection, board UI, live chat
  • Mobile: React Native companion app, built after the web frontend is complete
  • Milestone 4: Recoverable delete window (undo-delete within a time limit)
  • Milestone 5: Redis pub/sub for horizontal scaling across multiple server instances
  • Milestone 6: Load testing, Docker Compose, deployment

Each flagship project in this program follows the same sequence: backend → frontend → mobile, before moving to the next project.

Part of a Larger Program

This project is the first of three flagship builds in a structured mentorship track:

  1. RealTimeBoard — WebSockets, concurrency, state synchronization
  2. MarketFlow — multi-tenant data modeling, caching, security hardening
  3. PulseQueue — job queues, retry logic, observability, chaos testing

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages