WhatsApp CRM Architecture

Multi-tenant SaaS platform — app.queunir.com on OVH (192.99.145.61)

6
Active Slices
16
Controllers
13
Services
11
Pages
28
Components
15
Migrations

Request Flow

Browser
app.queunir.com
HTTPS :443
Nginx
SSL + proxy
:3000
Gateway
Auth + routing
:500X
Slice
Docker container

Nginx serves the SPA statically. API requests proxy through the Gateway to the user's assigned Slice container.

Multi-Tenant Slice Model

Each user gets an isolated Docker container (slice) with its own WhatsApp session, database, and media storage.

1
User signs up → Gateway provisions a new slice (~5 seconds from warm pool)
2
Provisioner creates PostgreSQL database (wa_slice_N), Docker container, port mapping
3
Slice starts Express + Puppeteer + Chromium → user scans QR code to connect WhatsApp
4
All API requests route through Gateway → proxied to user's slice on port 500X
ResourceIsolation
Databasewa_slice_1, wa_slice_2, etc.
WhatsApp Session/data/slices/{n}/session
Media Files/data/slices/{n}/media
Network Ports5001, 5003, 5005, 5007, 5009, 5011

Component Stack

Gateway systemd
Express + TypeScript. Auth, billing (Stripe), admin dashboard API, slice orchestration, health monitoring (60s interval).

11 source files: index, auth, admin (17KB), billing, monitor, orchestrator, provisioner, proxy, sse, database, health
Backend per-slice
Express + whatsapp-web.js + Puppeteer/Chromium.

16 controllers: status, chat, message, contact, media, mediaStorage, personality, actions, reminder, aiCrm, backfill, chatImport, contactImport, library, phrase

13 services: WhatsAppService (650 lines), DOMReader (57KB), MediaService (43KB), BackfillService, AIService, PersonalityService, and more
Frontend React SPA
React 18 + Vite + Tailwind + IBM Plex fonts. Dual-mode: standalone + SaaS (VITE_SAAS=1).

11 pages: ChatPage, MediaBrowser (43KB), AdminDashboard (40KB), Settings, AISettings, PhotoLibrary, Personalities, Actions, ContactMap, Login, SaasLogin

28 components: CrmPanel (33KB), MessageComposer (21KB), ChatList (18KB), and more
Database PostgreSQL 17.7
Gateway DB: wank_saas (users, slices, sessions, telemetry, events)

Slice DBs: wa_slice_N (contacts, messages, media, AI personalities, reminders, CRM fields)

15 migrations from initial schema through contact locations

DOM-Only Data Extraction

All WhatsApp data extraction reads from the rendered HTML DOM — never WhatsApp's internal window.Store.* APIs. This is a critical anti-detection measure. The DOMReader service (57KB) implements this pattern.

Required
document.querySelectorAll() to find rendered elements. Read <img> src for avatars. Read text from <span>, <div>. Navigate naturally (click, scroll).
Forbidden
window.Store.* method calls. client.getContactById(), chat.fetchMessages(). Any WhatsApp internal JS API functions.

Production Server

PropertyValue
ServerOVH VPS — 192.99.145.61
OSUbuntu 25.04
CPU16 vCPU
RAM64GB + 32GB swap
Disk350GB SSD
Cost$40.40/month
StackDocker 29.2.1, Node.js 20, PostgreSQL 17.7, Nginx 1.26.3
SecurityUFW (22/80/443), fail2ban, SSH key-only
Domainapp.queunir.com (Certbot SSL)

SaaS Phases All Complete

1. Auth Gateway
2. Shared Frontend
3. Orchestrator
4. Health Monitoring
5. Stripe Billing
6. Marketing Site
7. Admin Dashboard
8. Domain + SSL
Detailed docs → Architecture | Gateway | Backend | Frontend | Deployment | Database