# Documenso Architecture

This document provides a high-level overview of the Documenso codebase to help humans and agents understand how the application is structured.

## Overview

Documenso is an open-source document signing platform built as a **monorepo** using npm workspaces and Turborepo. The application enables users to create, send, and sign documents electronically.

```
┌─────────────────────────────────────────────────────────────────────────────┐
│                              Remix App (Hono Server)                        │
│                                 apps/remix                                  │
├─────────────┬─────────────┬─────────────┬─────────────┬─────────────────────┤
│  /api/v1/*  │  /api/v2/*  │ /api/trpc/* │ /api/jobs/* │   React Router UI   │
│  (ts-rest)  │   (tRPC)    │   (tRPC)    │  (Jobs API) │                     │
├─────────────┴─────────────┴─────────────┴─────────────┴─────────────────────┤
│                                                                             │
│  ┌─────────┐  ┌─────────┐  ┌─────────┐  ┌─────────┐  ┌─────────────────┐    │
│  │  @api   │  │  @trpc  │  │  @lib   │  │  @email │  │    @signing     │    │
│  │ (REST)  │  │  (RPC)  │  │  (CORE) │  │         │  │                 │    │
│  └─────────┘  └─────────┘  └────┬────┘  └─────────┘  └─────────────────┘    │
│                                 │                                           │
│              ┌──────────────────┼──────────────────┐                        │
│              │                  │                  │                        │
│         ┌────▼────┐       ┌─────▼─────┐      ┌─────▼─────┐                  │
│         │ Storage │       │   Jobs    │      │    PDF    │                  │
│         │Provider │       │  Provider │      │  Signing  │                  │
│         └────┬────┘       └─────┬─────┘      └─────┬─────┘                  │
│              │                  │                  │                        │
└──────────────┼──────────────────┼──────────────────┼────────────────────────┘
               │                  │                  │
        ┌──────┴──────┐    ┌──────┴──────┐    ┌──────┴──────┐
        │  Database   │    │   Inngest/  │    │ Google KMS/ │
        │     S3      │    │    Local    │    │    Local    │
        └─────────────┘    └─────────────┘    └─────────────┘
```

## Monorepo Structure

### Applications (`apps/`)

| Package                    | Description                                              | Port |
| -------------------------- | -------------------------------------------------------- | ---- |
| `@documenso/remix`         | Main application - React Router (Remix) with Hono server | 3000 |
| `@documenso/openpage-api`  | Public analytics API                                     | 3003 |
| `@documenso/docs`          | Documentation site                                       | 3004 |

### Core Packages (`packages/`)

| Package              | Description                                               |
| -------------------- | --------------------------------------------------------- |
| `@documenso/lib`     | Core business logic (server-only, client-only, universal) |
| `@documenso/trpc`    | tRPC API layer with OpenAPI support (API V2)              |
| `@documenso/api`     | REST API layer using ts-rest (API V1)                     |
| `@documenso/prisma`  | Database layer (Prisma ORM + Kysely)                      |
| `@documenso/ui`      | UI component library (Shadcn + Radix + Tailwind)          |
| `@documenso/email`   | Email templates and mailer (React Email)                  |
| `@documenso/auth`    | Authentication (OAuth via Arctic, WebAuthn/Passkeys)      |
| `@documenso/signing` | PDF signing (Local P12, Google Cloud KMS)                 |
| `@documenso/ee`      | Enterprise Edition features                               |
| `@documenso/assets`  | Static assets                                             |

### Supporting Packages

| Package                      | Description               |
| ---------------------------- | ------------------------- |
| `@documenso/app-tests`       | E2E tests (Playwright)    |
| `@documenso/tailwind-config` | Shared Tailwind config    |
| `@documenso/tsconfig`        | Shared TypeScript configs |

## Tech Stack

| Category | Technology                        |
| -------- | --------------------------------- |
| Frontend | React 18, React Router v7 (Remix) |
| Server   | Hono                              |
| Database | PostgreSQL 15, Prisma, Kysely     |
| API      | tRPC, ts-rest, OpenAPI            |
| Styling  | Tailwind CSS, Radix UI, Shadcn UI |
| Auth     | Arctic (OAuth), WebAuthn/Passkeys |
| Email    | React Email, Nodemailer           |
| Jobs     | Inngest / Local                   |
| Storage  | S3-compatible / Database          |
| PDF      | @libpdf/core, pdfjs-dist          |
| i18n     | Lingui                            |
| Build    | Turborepo, Vite                   |
| Testing  | Playwright                        |

## API Architecture

### API V1 (Deprecated)

- **Location**: `packages/api/v1/`
- **Framework**: ts-rest (contract-based REST)
- **Mount**: `/api/v1/*`
- **Auth**: API Token (Bearer header)
- **Status**: Deprecated but maintained

**Routes** (RESTful pattern):

- `GET/POST/DELETE /api/v1/documents/*`
- `GET/POST/DELETE /api/v1/templates/*`
- Recipients and fields nested under documents

### API V2 (Current)

- **Location**: `packages/trpc/server/`
- **Framework**: tRPC with trpc-to-openapi
- **Mount**: `/api/v2/*`, `/api/v2-beta/*`
- **Auth**: API Token or Session Cookie
- **Status**: Active

**Routes** (action-based pattern):

- `GET/POST /api/v2/document/*` - Document operations
- `GET/POST /api/v2/template/*` - Template operations
- `GET/POST /api/v2/envelope/*` - Envelope operations (multi-document)
- `GET/POST /api/v2/folder/*` - Folder management

**Route Organization**:

```
packages/trpc/server/
├── document-router/
│   ├── get-document.ts
│   ├── get-document.types.ts
│   └── ...
├── template-router/
├── envelope-router/
├── recipient-router/
├── field-router/
└── ...
```

### Internal tRPC API

- **Mount**: `/api/trpc/*`
- **Usage**: Frontend-to-backend communication
- **Auth**: Session-based

## Background Jobs

Jobs handle async operations like email sending, document sealing, and webhooks.

### Architecture

```
┌─────────────────┐     ┌───────────────────────────────────────┐
│ triggerJob()    │────▶│         Job Provider                  │
│                 │     │  ┌─────────────┬─────────────────┐    │
│ - name          │     │  │   Inngest   │      Local      │    │
│ - payload       │     │  │   (Cloud)   │   (Database)    │    │
└─────────────────┘     │  └─────────────┴─────────────────┘    │
                        │                │                      │
                        │                ▼                      │
                        │    ┌─────────────────────┐            │
                        │    │  Job Handler        │            │
                        │    │  (async processing) │            │
                        │    └─────────────────────┘            │
                        └───────────────────────────────────────┘
```

### Location

- `packages/lib/jobs/client/` - Provider implementations
- `packages/lib/jobs/definitions/` - Job definitions

### Job Types

**Email Jobs**:

- `send.signing.requested.email` - Signing invitation
- `send-confirmation-email` - Email verification
- `send-recipient-signed-email` - Notify on signature
- `send-rejection-emails` - Rejection notifications
- `send-document-cancelled-emails` - Cancellation notices

**Internal Jobs**:

- `internal.seal-document` - Finalize signed documents
- `internal.bulk-send-template` - Bulk document sending
- `internal.execute-webhook` - External webhook calls

## Swappable Providers

The codebase uses a **strategy pattern** with `ts-pattern` for provider selection via environment variables.

### Storage Provider

Handles file uploads and downloads.

| Provider | Description                          | Env Value  |
| -------- | ------------------------------------ | ---------- |
| Database | Store files as Base64 in DB          | `database` |
| S3       | S3-compatible storage (+ CloudFront) | `s3`       |

**Config**: `NEXT_PUBLIC_UPLOAD_TRANSPORT`

**Location**: `packages/lib/universal/upload/`

### PDF Signing Provider

Cryptographically signs PDF documents.

| Provider         | Description          | Env Value    |
| ---------------- | -------------------- | ------------ |
| Local            | P12 certificate file | `local`      |
| Google Cloud HSM | Google Cloud KMS     | `gcloud-hsm` |

**Config**: `NEXT_PRIVATE_SIGNING_TRANSPORT`

**Location**: `packages/signing/`

### Email Provider

Sends transactional emails.

| Provider     | Description                    | Env Value      |
| ------------ | ------------------------------ | -------------- |
| SMTP Auth    | Standard SMTP with credentials | `smtp-auth`    |
| SMTP API     | SMTP with API key              | `smtp-api`     |
| Resend       | Resend API                     | `resend`       |
| MailChannels | MailChannels API               | `mailchannels` |

**Config**: `NEXT_PRIVATE_SMTP_TRANSPORT`

**Location**: `packages/email/mailer.ts`

### Background Jobs Provider

Processes async jobs.

| Provider | Description           | Env Value         |
| -------- | --------------------- | ----------------- |
| Local    | Database-backed queue | `local` (default) |
| BullMQ   | Redis-backed queue    | `bullmq`          |
| Inngest  | Managed cloud service | `inngest`         |

**Config**: `NEXT_PRIVATE_JOBS_PROVIDER`

**Location**: `packages/lib/jobs/client/`

## Request Flow

### Web Application Request

```
Browser
   │
   ▼
Hono Server (apps/remix/server/)
   │
   ├──▶ /api/v1/* ──▶ ts-rest handlers (packages/api/)
   │
   ├──▶ /api/v2/* ──▶ tRPC OpenAPI handlers (packages/trpc/)
   │
   ├──▶ /api/trpc/* ──▶ tRPC handlers (packages/trpc/)
   │
   ├──▶ /api/jobs/* ──▶ Job handlers (packages/lib/jobs/)
   │
   └──▶ /* ──▶ React Router (apps/remix/app/routes/)
                    │
                    ▼
              React Components (packages/ui/)
```

### Document Signing Flow

```
1. Upload Document ──▶ Storage Provider (DB/S3)
                                  │
2. Add Recipients ────────────────┤
                                  │
3. Add Fields ────────────────────┤
                                  │
4. Send Document ─────────────────┤
       │                          │
       ▼                          │
   Email Job ──▶ Email Provider   |
       │                          |
5. Recipient Signs ───────────────┤
       │                          │
       ▼                          │
   seal-document Job              │
       │                          │
       ▼                          │
   Signing Provider ◀─────────────┘
       │
       ▼
   Signed PDF ──▶ Storage Provider
```

## Key Directories

```
documenso/
├── apps/
│   └── remix/
│       ├── app/
│       │   └── routes/           # React Router routes
│       │       ├── _authenticated+/  # Protected routes
│       │       ├── _unauthenticated+/  # Public routes
│       │       └── _recipient+/  # Signing routes
│       └── server/
│           ├── router.ts         # Hono route mounting
│           └── main.js           # Entry point
├── packages/
│   ├── api/v1/                   # API V1 (ts-rest)
│   ├── trpc/server/              # API V2 + Internal (tRPC)
│   ├── lib/
│   │   ├── server-only/          # Server business logic
│   │   ├── client-only/          # Client utilities
│   │   ├── universal/            # Shared code
│   │   └── jobs/                 # Background jobs
│   ├── prisma/                   # Database schema & client
│   ├── signing/                  # PDF signing
│   ├── email/                    # Email templates
│   └── ui/                       # Component library
└── docker/                       # Docker configs
```

## Development

```bash
# Full setup (install, docker, migrate, seed, dev)
npm run d

# Start development server
npm run dev

# Database GUI
npm run prisma:studio

# Type checking (faster than build)
npx tsc --noEmit

# E2E tests
npm run test:e2e
```

### Docker Services (Development)

| Service         | Port       |
| --------------- | ---------- |
| PostgreSQL      | 54320      |
| Inbucket (Mail) | 9000       |
| MinIO (S3)      | 9001, 9002 |

## Environment Variables Summary

| Variable                         | Purpose          | Options                                           |
| -------------------------------- | ---------------- | ------------------------------------------------- |
| `NEXT_PUBLIC_UPLOAD_TRANSPORT`   | Storage provider | `database`, `s3`                                  |
| `NEXT_PRIVATE_SIGNING_TRANSPORT` | Signing provider | `local`, `gcloud-hsm`                             |
| `NEXT_PRIVATE_SMTP_TRANSPORT`    | Email provider   | `smtp-auth`, `smtp-api`, `resend`, `mailchannels` |
| `NEXT_PRIVATE_JOBS_PROVIDER`     | Jobs provider    | `local`, `inngest`                                |

See `.env.example` for the complete list of configuration options.
