A real-time collaborative workspace built as a modular monolith — pairing Kanban boards and CRDT documents with a clean, microservice-ready architecture.
Architecture · Database · API · WebSockets · Realtime Engine · Auth & RBAC · Modules · Queue · DevOps · Testing · Security · Structure · Logging · Test Catalogs · Screenshots
- 1. Overview & Core Architecture
- 2. Deep-Dive Architecture & Engineering Specifications
- 2.1 System Architecture & Modular Monolith Topology
- 2.2 Database Architecture, LexoRank & Table Partitioning
- 2.3 REST API Design, Response Envelopes & Pagination
- 2.4 Real-Time WebSocket Protocol & Event Matrix
- 2.5 Collaborative Document Engine & Yjs CRDT
- 2.6 Authentication, Session Security & Multi-Tenant RBAC
- 2.7 Domain Modules & Sub-Feature Specifications
- 2.8 Message Queue, Asynchronous Processing & DLX Architecture
- 2.9 Infrastructure, Containerization & Object Storage
- 2.10 Testing Strategy & Automated Test Coverage
- 2.11 Security Practices & Checklist
- 2.12 Monorepo Project Structure & Placement Rules
- 2.13 Structured Logging, Error Envelopes & Observability
- 3. Frontend Companion (MVP Web Client Overview)
- 4. Getting Started & Quickstart Guide
SyncBoard is a real-time collaborative workspace built around a modular monolith backend in NestJS 11 and Node.js 20 LTS. It brings together fast, interactive Kanban boards, conflict-free rich-text document editing (via CRDTs), and multi-tenant workspace management. The system is designed with decoupled domain boundaries and event-driven communication, keeping deployment simple while remaining ready to extract into independent microservices as scale demands.
To showcase and test these backend capabilities end-to-end, the project includes a companion React 19 Single Page Application (SPA) client. The frontend handles real-time WebSocket relays, presence indicators, optimistic updates, and REST API envelopes in a responsive UI designed for desktop, tablet, and mobile.
Screenshots: UI captures are available in the
frontend/public/screenshots/folder, with descriptions infrontend/README.md.
┌────────────────────────────────────────────────────────────────────────┐
│ FRONTEND │
│ React 19 SPA · TypeScript 5 · Vite · Responsive Layout · Yjs Client │
│ Socket.IO Client · HTML5 Native Drag & Drop · SVG Icon System │
└───────────────────────────────────┬────────────────────────────────────┘
│ HTTP / WSS
┌───────────────────────────────────▼────────────────────────────────────┐
│ BACKEND │
│ Node.js 20 LTS · NestJS 11 Modular Monolith · Strict TypeScript │
│ Prisma ORM · Passport (RS256 JWT & OAuth) · LexoRank · Pino · Joi │
└───────┬───────────────────┬───────────────────┬────────────────┬───────┘
│ │ │ │
┌───────▼────────┐ ┌───────▼────────┐ ┌───────▼────────┐ ┌─────▼───────┐
│ PostgreSQL │ │ Redis 7 │ │ RabbitMQ 3.13 │ │ MinIO / S3 │
│ Relational DB │ │ Cache/Presence │ │ Message Broker │ │ Object Store│
│ Partitioning │ │ Socket Adapter │ │ DLX & Retries │ │ Presigned │
└────────────────┘ └────────────────┘ └────────────────┘ └─────────────┘
| Domain Feature | Architectural Capabilities | Primary Libraries & Technologies |
|---|---|---|
| Kanban Engine | Drag-and-drop board lists & cards, LexoRank |
lexorank, @hello-pangea/dnd, React 19, TypeScript |
| Card Domain Enrichment | Subcards (depth text, number, date, select, user), dependencies (blocks, relates_to), time tracking, priority (lowest…urgent), status (not_started…closed) |
Prisma ORM, PostgreSQL 16, class-validator, class-transformer
|
| Collaborative Docs | Real-time concurrent document editing, binary CRDT state vectors, debounced 5s persistence, awareness cursors, preview extraction |
yjs, socket.io, socket.io-client, PostgreSQL BYTEA
|
| Multi-View Projections | Realtime Kanban view, Sortable/Filterable Table view, Due-Date Calendar view, Creation Timeline view | React 19, SVG Icon System, CSS Modules |
| Realtime Presence | Multiplexed WebSocket rooms, dual-key Redis tracking (30s heartbeat, 60s reaping), per-event sliding window rate limiting |
socket.io, @socket.io/redis-adapter, ioredis
|
| Multi-Tenant RBAC | Strict workspace isolation, 4-tier roles (owner, admin, member, viewer), per-request DB role verification |
NestJS Guards, Passport.js, PostgreSQL relational joins |
| Auth & Sessions | RS256 15m access JWT, 7d rotating refresh tokens in HttpOnly cookies, token reuse family invalidation, Redis JTI blacklist |
jsonwebtoken, passport-jwt, passport-google-oauth20, bcrypt
|
| Async Messaging | Decoupled domain events, dead-letter exchanges (DLX), exponential backoff wait queues, idempotent consumers | RabbitMQ 3.13, @golevelup/nestjs-rabbitmq, amqplib, @nestjs/event-emitter
|
| 2-Phase File Uploads | Direct-to-storage presigned S3 uploads (pending /confirm completed), zero server RAM buffering |
AWS SDK v3 (@aws-sdk/client-s3, @aws-sdk/s3-request-presigner), MinIO |
| Time-Partitioned Audit | High-volume activity event logging, monthly range partitions, zero-cost partition dropping for data retention | PostgreSQL 16 Partitioned Tables, Custom SQL |
| Observability & Health | Structured JSON logging with field redaction, correlation IDs (X-Request-Id), Terminus probes |
pino, nestjs-pino, pino-http, @nestjs/terminus
|
| Test Coverage | 100% real unit test coverage across all backend services, controllers, listeners, and utilities (1,227+ passing unit tests) |
jest, supertest
|
This section summarizes each engineering document in sequence. For full implementation details, open the linked doc for that section.
SyncBoard is structured as a modular monolith running within a single NestJS process. The system combines strict domain encapsulation with the operational simplicity of a single deployable unit, while keeping modules cleanly decoupled so they can be extracted into standalone microservices:
-
Decoupled Domain Modules: Modules (
auth,workspace,board,document,notification,activity,file,mail) expose clear public service contracts with no direct cross-module database access. - Microservices-Ready: Domain boundaries and event-driven communication are designed so individual modules can be easily extracted into independent microservices when scaling requirements call for it.
-
Decoupled Event Bus: Side effects (audit logging, email dispatch, notification fan-out) are emitted as domain events via
EventEmitter2locally and published to RabbitMQ asynchronously. -
Pipeline Lifecycle: Incoming requests pass through an edge reverse proxy (Nginx with SSL termination and rate limiting)
$\to$ CorrelationIdInterceptor(X-Request-Id)$\to$ JwtAuthGuard(RS256 & Redis token blacklist)$\to$ WorkspaceMemberGuard(tenant RBAC verification)$\to$ ValidationPipe(strict DTO parsing)$\to$ Domain Services$\to$ Prisma ORM$\to$ Standardized Envelope Response.
→ Architecture Overview — topology, request pipeline, and module boundary rules.
The persistent storage tier is powered by PostgreSQL 16 with schemas managed through Prisma ORM and enriched with custom SQL migrations for advanced indexing, constraints, and partitioning:
- Relational Schema: Enforces relational integrity across multi-tenant boundaries (Users, Workspaces, WorkspaceMembers, Boards, BoardLists, Cards, Comments, Attachments, Documents, and Activities).
-
Custom PostgreSQL ENUMs: Domain-level types (
workspace_role,card_priority,card_status,attachment_status_enum,invitation_status). -
LexoRank Algorithm (
$O(1)$ Ordering): Reordering cards or lists updates only the single affected row using string-based fractional indexing midpoints (e.g."0|hzzzzz:"and"0|i00000:"$\to$ "0|hzzzzz:8"), eliminating cascading table write locks. -
Time-Partitioned Audit Logs: The
activitiestable utilizes PostgreSQL monthly range partitioning (PARTITION BY RANGE (created_at)), ensuring high write throughput and zero-cost historical partition dropping for data retention compliance. -
Composite & Partial Indexes: Targeted indexing for active records (
WHERE deleted_at IS NULL), pending invitation email lookups, and fast card list ordering.
→ Database Design — ER diagrams, SQL schemas, partition triggers, and indexing strategies.
SyncBoard's REST API adheres to strict consistency and predictable contract envelopes across all endpoints:
- Standard Envelope Format: Every response is wrapped in a consistent structure:
- Success:
{ success: true, data: T, meta: { timestamp, requestId, pagination? } } - Error:
{ success: false, error: { code, message, details? }, meta: { timestamp, requestId } }
- Success:
- Dual Pagination Architecture:
- Keyset / Cursor Pagination (
cursor,limit): Used for high-frequency or unbounded append-only feeds (activity logs, notifications, comments) to guarantee deterministic reads without offset-drift. - Offset Pagination (
page,limit): Used for bounded administrative grids (workspace lists, member rosters).
- Keyset / Cursor Pagination (
- Idempotency Controls: Mutation operations accept an
Idempotency-Keyheader cached in Redis to guard against duplicate transactions from network retries. - Sliding-Window Rate Limiting: Enforced globally and tuned per-route (stricter limits on
/api/auth/*endpoints) using Redis sliding logs.
→ API Design — error codes, header contracts, and pagination specs. Interactive schema at /api/docs.
Real-time capabilities are orchestrated via Socket.IO 4.8 backed by @socket.io/redis-adapter for seamless horizontal scalability:
-
Multiplexed Gateways: Separated into dedicated gateways (
BoardGateway,DocumentGateway,NotificationPushGateway). -
Room-Scoped Isolation: Sockets join fine-grained rooms (
board:${boardId},doc:${documentId},user:${userId}). Broadcasts are strictly isolated to authenticated members of the active room. -
Dual-Key Presence Engine:
- Redis
SETwith 30s TTL periodically refreshed by client heartbeat pings. - Redis Sorted Set (
ZSET) storing timestamps for deterministic viewer counting and ghost reaping (60s inactivity threshold).
- Redis
- Event Relay Contracts: Immediate client reflection for board modifications, card moves, list reorganizations, and viewer joining/leaving notifications.
→ WebSocket Events — full event list, payload schemas, and presence algorithms.
Collaborative document editing leverages Yjs 13.6 Conflict-free Replicated Data Types (CRDTs) to guarantee convergence without centralized merge locks:
- Binary State Vector Sync: Two-step handshake (
sync-step-1exchanging local state vectors,sync-step-2streaming missing binary updates) ensures minimal bandwidth consumption. - In-Memory Buffer with Debounced Persistence: Active document sessions are maintained in server memory. Document updates are accumulated and flushed to PostgreSQL
BYTEAstorage on a 5-second debounce window or upon session teardown. - Real-Time Awareness: Broadcasts peer cursor selections, remote carets, display names, and distinct avatar colors without database writes.
- Snapshot Versioning: Periodic named snapshots allow workspace members to inspect historical revisions and restore documents to prior states.
→ Realtime Engine — CRDT state vector lifecycle, debounce flush, and awareness protocols.
The authentication and session architecture is designed for secure token handling and strict multi-tenant isolation:
- RS256 Asymmetric Tokens: Access tokens (15-minute lifetime) are signed via private RSA key and verified with a public key, eliminating database lookups on authenticated REST calls.
- Rotating Refresh Tokens in HttpOnly Cookies: 7-day refresh tokens are securely stored in
HttpOnly,SameSite=Strictcookies. Each refresh request issues a new token pair and invalidates the previous token. - Reuse Detection & Family Invalidation: Replaying an expired or previously consumed refresh token triggers immediate invalidation of the entire user session family.
- Redis JTI Blacklist: Logout (
/api/auth/logout) and global revocation (/api/auth/logout-all) record token JTIs in Redis with remaining TTLs to instantly revoke compromised access tokens. - Hierarchical Workspace RBAC: 4 distinct roles (
owner>admin>member>viewer) verified per-request byWorkspaceMemberGuardto ensure tenant isolation.
→ Auth & RBAC — token flow diagrams, cryptographic specs, and RBAC matrix.
The core business logic is organized into clean domain modules supporting an extensive collaborative feature set:
- Workspaces & Members: Tenant creation, slug generation, email invitations, member administration, and ownership transfer.
- Boards & Lists: Customizable Kanban boards, list workflow stages, board starring, background colors, and soft-delete archiving.
-
Cards & Subcards: Cards support rich descriptions, priority flags (
lowesttourgent), and hierarchical subcards (depth$\le 2$ ) with automatic parent completion percentage calculation. -
Custom Fields System: Flexible custom attribute definitions (
text,number,date,select,user) attached to cards with strict type validation. - Time Tracking: Granular work duration logging with start/end timestamps, billable status, and per-card aggregate metrics.
- Checklists: Task checklists with toggleable items and real-time progress bars.
-
Card Attachments & Dependencies: S3 file metadata management and dependency linking (
blocks,is_blocked_by,relates_to). -
Comments &
@mentions: Threaded discussion trees (depth$\le 1$ ), mention parsing regex (/@([a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,})/gi), canonical email normalization, and asynchronous member notification fan-out.
→ Module Specs — entity schemas, validation rules, and business logic per domain.
SyncBoard uses RabbitMQ 3.13 via @golevelup/nestjs-rabbitmq for background processing and decoupled event streaming:
- Topic Exchanges:
notification.exchange: Routes card assignments, mentions, and role changes (notification.*).activity.exchange: Ingests high-velocity audit log events (activity.*).email.exchange: Dispatches transactional verification and invite emails (email.*).
- Dead-Letter Exchange (DLX) & Exponential Backoff:
- Poison or failing messages route to
notification.dlxwith configured retry queues (x-dead-letter-exchange,x-message-ttl). - Exponential backoff delays retries up to 3 times before terminal dead-lettering.
- Poison or failing messages route to
- Idempotent Consumers: Consumers implement
consumeOnceleveraging Redis atomic keys (msg:processed:<id>) to guarantee exactly-once execution despite network duplicates.
→ Message Queue Design — queue topology, retry policies, and routing key constants.
The repository provides automated Docker Compose definitions enabling one-command local startup of the complete platform:
- Container Topology: PostgreSQL 16 (Primary), Redis 7, RabbitMQ 3.13, MinIO S3, and MailHog SMTP daemon.
- Full Stack Profile (
--profile full): Launches PostgreSQL streaming read replicas, a transaction-mode PgBouncer connection pooler, and an Nginx edge proxy with sticky sessions. - 2-Phase Presigned S3 Uploads:
- Client sends file metadata to
POST /api/cards/:id/attachments/presign. - Backend signs a direct S3 PUT URL via
@aws-sdk/s3-request-presigner. - Client uploads directly to MinIO/S3 (zero server RAM consumption).
- Client invokes
POST /confirmto verify object size and activate attachment metadata.
- Client sends file metadata to
→ Infrastructure & DevOps — Docker Compose configs, port mappings, and S3 CORS policies.
The codebase is thoroughly tested with an automated unit test suite:
- 100% Unit Test Coverage: Every service, controller, repository, interceptor, guard, and event listener maintains 100% branch, statement, function, and line coverage.
- Isolated Unit Tests: Tests execute with isolated unit mocks and in-memory repositories, ensuring fast and reliable CI runs without external network dependencies.
- 1,227+ Passing Tests: Automated test suite covering all core business domains.
# Run complete unit test suite with coverage report
npm run test:cov→ Testing Strategy — methodology, test categories, and coverage thresholds.
SyncBoard implements layered security controls across the application:
- HTTP Header Protection: Configured with
helmetfor Content Security Policy (CSP), Strict-Transport-Security (HSTS), and clickjacking prevention. - Strict CORS Controls: Whitelisted origins with credential support (
Access-Control-Allow-Credentials: true). - Input Validation & Sanitization:
ValidationPipewithwhitelist: trueandforbidNonWhitelisted: trueprevents parameter injection and mass assignment. - Password Hashing: Salted cryptographic hashing powered by
bcrypt(12 rounds). - Upload Security: Magic-byte MIME type inspection, file extension whitelisting, and strict size caps on S3 presigned URLs.
→ Security Checklist — full production security checklist.
The codebase maintains a clear modular structure and separation of concerns:
- Backend (
src/): Organized intomodules/<domain>/containing dedicated subdirectories forcontrollers,services,repositories,dto,events, andlisteners. - Shared Infrastructure (
src/common/): Reusable components (database,redis,rabbitmq,guards,interceptors,filters,exceptions,utils). - Companion Frontend (
frontend/): Modular React 19 SPA client organized by features, shared UI components, API clients, and state stores.
→ Project Structure — directory maps, naming conventions, and import boundaries.
Observability and structured logging are built directly into the application:
- Structured JSON Logging: Powered by
pinoandnestjs-pinowith automatic field redaction (masking passwords, JWTs, and authorization headers). - Distributed Request Tracing:
X-Request-Idcorrelation IDs follow each operation across HTTP requests, service executions, and background message queues. - Exception Hierarchy: Unified application exceptions (
AppException,BusinessRuleException,EntityNotFoundException) caught byGlobalExceptionFilterand formatted into standard error envelopes. - Health Probes: Terminus endpoints at
/api/healthreport live health checks on PostgreSQL, Redis, RabbitMQ, and object storage.
→ Logging & Observability — error envelopes, log levels, and health monitoring.
To provide an intuitive, production-grade interface for testing and interacting with the backend architecture, SyncBoard includes a responsive React 19 Single Page Application (SPA) client built with TypeScript, Vite, and modern CSS:
- Interactive Kanban Board: Drag-and-drop lists and cards with real-time LexoRank position syncing and optimistic UI updates.
- CRDT Document Editor: Real-time collaborative document editing synchronized over Yjs WebSockets with remote awareness cursors and autosave indicators.
- Multi-View Projections: Smooth switching between Kanban Board, Sortable Data Table, Due-Date Calendar, and Creation Timeline views.
- Card Detail Hub: Subcards with progress rollups, custom fields, checklists, time tracking logs, file attachments, and dependency links.
- Comment
@mentionsSystem: Typing@triggers autocomplete for workspace members, normalizes mentions to canonical emails, and displays styled@DisplayNamebadges with full-name tooltips. - Real-Time Notification Popover: Live unread badge count updated via WebSockets with deep-link navigation directly into cards and comment threads.
- Responsive Layout: Mobile navigation drawer, fluid grids, and a crisp SVG vector icon system that adapts smoothly from phones to widescreen monitors.
📸 Screenshots: All screenshots are stored in the
frontend/public/screenshots/folder. To view them with descriptions of each interface and view, see Frontend Screenshots.
Depending on your preferred setup:
- Docker & Docker Compose: Docker Engine
24.x+and Docker Composev2.x+(required for all containerized workflows) - Node.js:
20.x LTSor higher (required only if running backend or frontend outside Docker) - npm:
10.xor higher - PostgreSQL Client (
psql): (required only if initializing the database manually on your host)
# Clone the repository
git clone https://github.com/1mimhe/sync-board.git
cd sync-board
# Copy environment template
cp .env.example .env(The default .env is pre-configured with dev/docker defaults that work out-of-the-box).
SyncBoard supports three run workflows tailored to different development needs:
┌─────────────────────────────────────────────────────────────────────────────┐
│ Which way should I run SyncBoard? │
│ │
│ 1. Just want to test/evaluate the platform? ──> Way 1 (Full Docker Stack) │
│ 2. Working primarily on the React frontend? ──> Way 2 (Docker App + UI Dev) │
│ 3. Developing backend & frontend with HMR? ──> Way 3 (Infra Only + Local) │
└─────────────────────────────────────────────────────────────────────────────┘
Runs the entire platform inside Docker: Postgres, Redis, RabbitMQ, MinIO (with auto-created bucket), MailHog, NestJS backend (with auto-generated RSA keys), React frontend, and Nginx edge reverse proxy. No local Node.js installation required.
# Start all services with automated migrations, partitions, indexes, and demo data
docker compose --profile full up -d
# Verify all containers are healthy
docker compose psTip
Demo data is seeded automatically. To start with an empty database:
RUN_SEED=false docker compose --profile full up -d- Access the App: http://localhost (Nginx edge proxy on port 80)
- API Documentation (Swagger): http://localhost/api/docs
- Stop the stack:
docker compose --profile full down
Runs all databases, queues, and the NestJS backend in Docker. You run only the React Vite dev server on your host machine with instant Hot Module Replacement (HMR).
# 1. Start backing services + automated DB init + NestJS backend
docker compose --profile app up -d
# 2. In a new terminal, launch the frontend dev server
cd frontend
npm install
npm run dev- Frontend: http://localhost:5173 (automatically proxies
/apiand/socket.ioto backend on:3000) - Backend Swagger: http://localhost:3000/api/docs
- Stop backend:
docker compose --profile app down
Best for active backend development. Only Postgres, Redis, RabbitMQ, MinIO, and MailHog run in Docker; NestJS and React run directly on your host machine with file watchers and IDE debuggers.
# 1. Start core backing infrastructure
docker compose up -d
docker compose ps
# 2. Install backend dependencies and generate Prisma client
npm install
npx prisma generate
# 3. Push database schema, apply custom SQL & seed demo data
npm run db:push
psql postgresql://syncuser:syncpass@localhost:5432/syncboard?schema=public -f prisma/activity-partitions.sql
psql postgresql://syncuser:syncpass@localhost:5432/syncboard?schema=public -f prisma/custom-indexes.sql
npm run db:seed
# 4. Start NestJS in watch mode (Terminal 1)
npm run start:dev
# 5. Start React Vite frontend (Terminal 2)
cd frontend
npm install
npm run dev- Frontend: http://localhost:5173
- Backend API: http://localhost:3000/api
- Swagger Docs: http://localhost:3000/api/docs
- Stop infra:
docker compose down
| Service / Interface | URL (Full Stack / Nginx) | URL (Direct / Local) | Credentials / Purpose |
|---|---|---|---|
| Web Application | http://localhost | http://localhost:5173 | React SPA |
| Backend REST API | http://localhost/api | http://localhost:3000/api | NestJS application endpoints |
| Swagger API Docs | http://localhost/api/docs | http://localhost:3000/api/docs | Interactive OpenAPI exploration |
| API Health Probe | http://localhost/api/health | http://localhost:3000/api/health | Health status (Postgres, Redis, RabbitMQ) |
| RabbitMQ Management | — | http://localhost:15672 | guest / guest |
| MinIO Object Console | — | http://localhost:9001 | minioadmin / minioadmin |
| MailHog Web Inbox | — | http://localhost:8025 | Local email capture interface |
The database seed script initializes the following accounts:
| User Role | Email Address | Password | Permissions |
|---|---|---|---|
| Platform Admin / Owner | admin@syncboard.dev |
Password123! |
Full workspace ownership & settings |
| Team Member | alex@syncboard.dev |
Password123! |
Active collaboration & card management |
| Guest / Viewer | sarah@syncboard.dev |
Password123! |
Read-only board and document access |
# ── Testing ───────────────────────────────────────────────────────────────
npm run test # Run unit tests
npm run test:cov # Run unit tests with coverage report
npm run test:e2e # Run end-to-end integration tests
# ── Code Quality ──────────────────────────────────────────────────────────
npm run lint # Run ESLint fix
npm run format # Run Prettier format
cd frontend && npm run lint # Lint frontend code with Oxlint
# ── Database ─────────────────────────────────────────────────────────────
npm run db:push # Sync Prisma schema to database
npm run db:seed # Seed sample data
docker compose exec postgres-primary psql -U syncuser -d syncboard # Postgres CLI
docker compose exec redis redis-cli # Redis CLI
# ── Docker Maintenance ───────────────────────────────────────────────────
docker compose ps # Check container status
docker compose logs -f app # Tail backend logs
docker compose --profile full up -d --build # Rebuild and restart
docker compose --profile full down -v # Wipe all containers and data volumesMade with ❤️
