DeskcommCRM Architecture: Deep Dive into the AI-Native Sales CRM Built on Next.js and Supabase

DeskcommCRM is a multi-tenant, AI-native sales platform that combines a Next.js 16 frontend, Supabase Postgres with Row-Level Security, WAHA WhatsApp integration, and a dedicated agent-engine powered by the Vercel AI Gateway to deliver automated conversational sales workflows.

The architecture of DeskcommCRM prioritizes data isolation, extensibility, and first-class AI integration. According to the melgarafael/DeskcommCRM source code, the system runs as a VPS-hosted application with distinct layers for data persistence, message ingestion, AI orchestration, and background job processing.

Core Application Layer (Next.js 16 + React 19)

The foundation of DeskcommCRM is a modern Next.js application using the App Router pattern with TypeScript.

App Router and Tenant Isolation

The authenticated user interface lives in app/app/, while platform administration resides in app/admin/. Server Actions handle onboarding, settings, and workflow configurations. The UI components leverage React 19 features and a custom design system located in app/design/lib/.

API Handlers and Edge Middleware

REST endpoints are versioned under /api/v1/ and located in app/api/v1/. Each handler validates input using Zod, enforces Role-Based Access Control (RBAC) via requireRole(), and returns standardized responses through ok() and fail() utilities. The edge middleware (proxy.ts) injects a global X-Request-Id header and performs authentication guards before the Next.js router executes.

Multi-Tenant Data Layer (Supabase + RLS)

DeskcommCRM implements strict multi-tenancy through PostgreSQL Row-Level Security (RLS) policies.

Schema Design and Security Policies

All tenant-aware tables include an organization_id column protected by RLS rules defined in supabase/migrations/. This ensures complete data isolation between organizations at the database level. The migration files are versioned, with the baseline schema stored in supabase/baseline.sql for idempotent fresh installations.

Service-Role Access and Migrations

Internal routes bypass RLS using a service-role client defined in lib/supabase/admin.ts. Every query using this client must explicitly filter by organization_id to maintain security boundaries. Schema changes ship as numbered migrations (e.g., 0023_ai_agents_module, 0040_conversation_routing_emit) with a comprehensive manifest documented in supabase/migrations/MANIFEST.md.

WhatsApp Integration Architecture (WAHA)

The platform integrates WhatsApp messaging through WAHA, an external engine using the NOWEB protocol.

Inbound Message Ingestion

Incoming WhatsApp events are processed by lib/waha/ingest.ts, which creates channel sessions and emits structured events to the event_log table (e.g., lead.created, message.inbound). The system includes regex-based unsubscribe detection defined in lib/waha/stop-detection.test.ts for compliance handling.

Media Handling and Storage

Outbound media is stored in private Supabase buckets with a media.persist_requested status. Signed URLs are generated through the endpoint GET /api/v1/messages/{id}/media, ensuring secure temporary access to files without exposing storage credentials.

AI Agent Engine and Runtime

The AI-native capabilities center on a sophisticated agent-engine located in lib/agent-engine/ and lib/ai/.

Vercel AI Gateway Integration

The lib/ai/gateway.ts file wraps the Vercel AI Gateway, handling provider selection between Anthropic, OpenAI, and custom endpoints with automatic fallback logic. This abstraction adds per-tenant observability and rate limiting before routing requests to underlying LLM providers.

Turn-Based Job Queue System

AI operations are scheduled through a priority job queue implemented in lib/agent-engine/queue/queue.ts. The queue uses PostgreSQL's FOR UPDATE SKIP LOCKED mechanism for efficient worker coordination, tracking jobs through statuses: open, running, and dead. Events trigger AI processing via ai_agent.dispatch_requested, resolved by lib/ai/dispatch.ts to schedule specific turns.

Background Worker Processes

Isolated worker containers (defined in Dockerfile.worker) consume the job queue asynchronously. The workers/ai-response-worker.handler.ts executes model calls through runModelCall() in lib/ai/runtime/agent.ts, automatically injecting RAG context and embeddings from lib/ai/embed.ts (using OpenAI's text-embedding-3-large). Additional workers handle sentiment analysis (workers/ai-sentiment-worker.ts) and media persistence.

Conversation Routing and Automation

After conversation creation, database triggers like trg_conversation_routing_requested emit routing events. The lib/routing/worker.ts processes these events according to organizational configurations:

  • Round-robin: Distributes conversations evenly across team members
  • Load-based: Assigns to the least-busy agent
  • Manual: Queues for human assignment

The routing system shares infrastructure with the follow-up scheduler, which generates followup_turn jobs processed by dedicated workers for timed re-engagement.

Frontend and Real-Time Updates

The presentation layer uses shadcn/ui components styled with Tailwind CSS 4. The inbox interface (components/inbox/) renders messages, AI-generated replies, and media attachments. Real-time synchronization is achieved through Supabase Realtime listeners using useRealtime() hooks that watch the messages, conversations, and event_log tables for live updates without polling.

Deployment and Operations

DeskcommCRM uses a containerized deployment strategy with three distinct Docker images:

  1. app: The Next.js application server (Dockerfile)
  2. worker: Background job processors (Dockerfile.worker)
  3. scheduler: Cron-driven task runners (Dockerfile.scheduler)

Production deployments utilize Traefik as a reverse proxy (configured in docker-compose.traefik.yml). Environment configuration (documented in .env.example) requires AI_GATEWAY_API_KEY for AI features, along with optional provider-specific keys like OPENAI_API_KEY and ANTHROPIC_API_KEY.

Summary

  • DeskcommCRM implements a multi-tenant architecture using Supabase RLS with organization_id scoping on every table
  • The AI Agent Engine uses a PostgreSQL-backed job queue with FOR UPDATE SKIP LOCKED for reliable worker distribution
  • WhatsApp integration occurs through WAHA ingestion pipelines that create normalized event logs
  • Next.js 16 serves both the React frontend and REST API handlers with Zod validation and RBAC middleware
  • Vercel AI Gateway provides unified access to multiple LLM providers with tenant-aware observability
  • Background workers run in isolated Docker containers for AI inference, sentiment analysis, and conversation routing

Frequently Asked Questions

How does DeskcommCRM ensure data isolation between tenants?

DeskcommCRM implements strict data isolation through PostgreSQL Row-Level Security (RLS) policies defined in supabase/migrations/. Every tenant-aware table includes an organization_id column, and RLS policies enforce that queries return only rows matching the current tenant. The service-role client in lib/supabase/admin.ts bypasses RLS for internal operations but requires explicit organization_id filters in application code.

What AI providers does the agent-engine support?

The agent-engine supports multiple providers through the Vercel AI Gateway abstraction in lib/ai/gateway.ts. The system can route requests to Anthropic (Claude), OpenAI (GPT models), or custom endpoints with automatic fallback between providers. Embeddings use OpenAI's text-embedding-3-large model via lib/ai/embed.ts for knowledge-base indexing.

How are WhatsApp messages processed in the architecture?

Inbound WhatsApp messages enter through WAHA and are processed by lib/waha/ingest.ts, which creates channel sessions and emits event_log entries. Outbound messages are queued through the agent-engine's job system in lib/agent-engine/queue/queue.ts, with media stored in private Supabase buckets and served via signed URLs through the /api/v1/messages/{id}/media endpoint.

What triggers AI agent responses in conversations?

AI responses are triggered by the ai_agent.dispatch_requested event, handled by lib/ai/dispatch.ts. This resolves the appropriate published agent version and schedules a turn in the job queue. Workers in workers/ai-response-worker.handler.ts execute the actual model calls through runModelCall() with RAG context injection, then write responses back to the conversation thread.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →