> ## Documentation Index
> Fetch the complete documentation index at: https://chatbotx.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# How it works

> Learn the architecture of the project

ChatbotX is composed of **3 main services** and **3 external services**. All running inside a single Docker environment, and communicating with each other.

## Architecture

```mermaid theme={null}
flowchart TD
    classDef svc fill:#9900e6,color:white,stroke:#fff
    classDef ext fill:#8ED14F,color:black,stroke:#fff

    user(["👤 User"])

    subgraph Internal Services
        Builder["Builder\n(Next.js App Router)"]:::svc
        Worker["Worker\n(BullMQ)"]:::svc
        Realtime["Realtime\n(WebSocket)"]:::svc
    end

    subgraph External Services
        Redis[("Redis")]:::ext
        DB[("PostgreSQL")]:::ext
        Storage[("Storage")]:::ext
    end

    user -->|"HTTP / REST"| Builder
    user <-->|"WebSocket"| Realtime

    Builder -->|"enqueue jobs"| Redis
    Builder -->|"read / write"| DB
    Builder -->|"upload / fetch"| Storage
    Builder -->|"send realtime events"| Realtime

    Worker -->|"consume queue"| Redis
    Worker -->|"read / write"| DB
    Worker -->|"read / write"| Storage
```

## Services

### Internal Services

<CardGroup cols={3}>
  <Card title="Builder" icon="browser" href="#builder">
    The main web application, serves the UI and handles all HTTP requests.
  </Card>

  <Card title="Worker" icon="gears" href="#worker">
    Processes background jobs enqueued by the Builder.
  </Card>

  <Card title="Realtime" icon="bolt" href="#realtime">
    Maintains persistent WebSocket connections and pushes realtime updates to clients.
  </Card>
</CardGroup>

### External Services

<CardGroup cols={3}>
  <Card title="Redis" icon="server" href="#redis">
    Used as a job queue (BullMQ), a cache service, and a pub/sub channel for realtime messaging.
  </Card>

  <Card title="PostgreSQL" icon="database" href="#postgresql">
    The primary relational database. All persistent application data is stored here.
  </Card>

  <Card title="Storage" icon="hard-drive" href="#storage">
    Object storage for user-uploaded files and generated assets.
  </Card>
</CardGroup>

## Builder

The **Builder** is a [Next.js App Router](https://nextjs.org/docs/app) application that acts as the single entry point for all user interactions.

* Renders the full UI via React Server Components and Client Components
* Exposes API routes that handle authentication, data mutations, and business logic
* Authenticates users via [Better Auth](https://github.com/better-auth/better-auth)
* Validates forms and API payloads with [Zod](https://zod.dev)
* Reads and writes application data to [PostgreSQL](#postgresql) through [DrizzleORM](https://orm.drizzle.team/)
* Uploads and retrieves files from [Storage](#storage)
* Enqueues background jobs into [Redis](#redis) for the Worker to process

## Worker

The **Worker** is a long-running Node.js process powered by [BullMQ](https://docs.bullmq.io) that handles all asynchronous and scheduled work.

* Consumes job queues from [Redis](#redis)
* Retries failed jobs with configurable back-off strategies
* Supports delayed and recurring (cron) job scheduling
* Reads and writes data to [PostgreSQL](#postgresql) as part of job execution
* Reads and writes files from [Storage](#storage) for processing tasks
* Runs independently of the Builder so heavy work never blocks HTTP responses

## Realtime

**Realtime** is a lightweight WebSocket server that keeps clients in sync without polling.

* Maintains persistent WebSocket connections with browser clients
* Subscribes to [Redis](#redis) pub/sub channels to receive events published by the Builder or Worker
* Broadcasts updates to the relevant connected clients in real time
* Reads application state from [PostgreSQL](#postgresql) when a client first connects

## Redis

**Redis** serves three distinct roles in the system:

| Role                   | Used by                                           |
| ---------------------- | ------------------------------------------------- |
| **Job queue** (BullMQ) | Builder enqueues → Worker consumes                |
| **Pub/sub channel**    | Builder / Worker publish → PartySocket subscribes |
| **Cache**              | Caches expensive queries and computed results     |

## PostgreSQL

**PostgreSQL** is the single source of truth for all persistent data.

* Schema is managed and migrated with [DrizzleORM](https://orm.drizzle.team/)
* Accessed by the Builder for request-time reads and writes
* Accessed by the Worker during background job execution

## Storage

**Storage** holds all binary assets and generated files.

* Compatible with any S3-compatible provider (AWS S3, MinIO, Cloudflare R2, etc.)
* The Builder uploads user files and retrieves signed URLs for serving
* The Worker reads source files and writes processed output during job execution

## Request Workflows

### GET Requests (Server Component)

```mermaid theme={null}
sequenceDiagram
  Note over Browser,NextServer: nuqs parses URL params
  Browser->>NextServer: GET /space/[workspaceId]/feature?page=2
  NextServer->>Drizzle: db.query.myModel.findMany(...)
  Drizzle-->>NextServer: return rows
  NextServer-->>Browser: render Server Component
```

### Mutations via Server Actions (next-safe-action)

```mermaid theme={null}
sequenceDiagram
  Note over Browser,NextServer: next-safe-action
  Browser->>NextServer: server action call (POST)
  NextServer->>Drizzle: db.insert / update / delete
  Drizzle-->>NextServer: result
  NextServer-->>Browser: revalidatePath / revalidateTag → reload
```

### API Requests via oRPC

```mermaid theme={null}
sequenceDiagram
  Browser->>NextServer: POST /rpc  (or GET /api/...)
  NextServer->>oRPC: router.procedure.handler(input)
  oRPC->>Drizzle: db query
  Drizzle-->>oRPC: result
  oRPC-->>NextServer: typed response
  NextServer-->>Browser: JSON
```

### Background Jobs (BullMQ)

```mermaid theme={null}
sequenceDiagram
  NextServer->>Redis: queue.add(jobName, data)
  Redis-->>Worker: dequeue job
  Worker->>Drizzle: db query / update
  Worker-->>Redis: mark complete
```
