Self-hosting overview
A 3x deployment consists of three parts:
| Part | What it is | Runs on |
|---|---|---|
API (apps/api) | Hono on Node 22: ingest, REST API, OpenAPI, docs, MCP server, OAuth, scheduler | Vercel function or any Node host |
Dashboard (apps/dashboard) | Next.js App Router, server components only talk to the API | Vercel or any Next.js host |
| Postgres | all data; one database for all tenants | Neon (recommended) or any Postgres ≥ 15 |
The browser SDK is served by the API (/v1/s/x3.js) and published as @3x-engine/sdk on npm.
Options
- Vercel + Neon – two Vercel projects from the same repository, Neon's pooled and direct connection strings, Vercel Cron for background jobs.
- Standalone Node –
node apps/api/dist/server.mjswith the in-process scheduler, behind nginx/Caddy/Cloudflare.
Minimum production configuration
| Variable | Notes |
|---|---|
X3_ENV=production | enables live conversion uploads and strict checks |
X3_DATABASE_URL, X3_DATABASE_URL_UNPOOLED | pooled for requests, direct for migrations and long jobs |
X3_PUBLIC_API_URL, X3_DASHBOARD_URL | public origins, used in links, OAuth metadata and CORS |
X3_SECRET | ≥ 32 characters, HMAC secret (CSRF, OAuth state, keyed hashes) |
X3_ENCRYPTION_KEY | 32 bytes base64, AES-256-GCM key for destination secrets |
CRON_SECRET | protects /v1/cron/* |
X3_DASHBOARD_KEY | ≥ 32 characters, same value on API and dashboard |
Generate secrets with
node -e "console.log(require('crypto').randomBytes(32).toString('base64'))". All variables:
Environment reference.
Operator responsibilities
- Data processing agreement with every tenant: visitor IPs reach the API (directly or via the site's proxy), so the deployment operator is a processor (Privacy).
- Backups of Postgres (Neon: point-in-time restore; elsewhere
pg_dumpor WAL archiving). - Composio project and ad-platform apps, if ad costs are offered (Composio setup).
- Upgrades and migrations (Upgrading).
- Keeping
X3_TRUSTED_IP_HEADERScorrect for the hosting platform – wrong values allow spoofed IPs and break budgets and session stitching.