/ docs / self-host

# Run your own CRRT.

CRRT is OSS-first. crrt.ai is the easy path, but the same code runs on your own infra in under twenty minutes if you'd rather own the stack.

## Hosted vs self-host

Prop

Type

Required

Description

`crrt.ai`

`managed`

optional

Sign up, create a project, paste the snippet. We run the API, the DB, and the agent bridge.

`self-host`

`OSS`

optional

You run the API + dashboard + DB. Full control, no third-party data hop, paid tier features come built-in.

The OSS and hosted versions are the same code on the same trunk. You can switch from hosted to self-host (or back) by changing `apiBase` on the widget.

## What you'll need

*   **Postgres** for the data layer. Any provider works; we recommend [Supabase](https://supabase.com) so you get auth + storage in the same place — that's what the hosted instance runs on.
*   **A runtime** that can serve the Vercel-style serverless functions in `api/` plus the static builds in `apps/landing/` and `apps/dashboard/`. We deploy to Vercel; Fly, Render, Cloudflare Workers, or a Node container all work.
*   **Bun ≥ 1.1** for the build commands (`bun install`, `bun run build`).

## 1\. Clone and install

bash

```
git clone https://github.com/thedesignproject/CRRT.git
cd CRRT
bun install
```

## 2\. Configure environment

Copy `.env.example` to `.env` and fill in the required values. The dashboard includes the public `SUPABASE_KEY` in its browser bundle at build time. Keep `SUPABASE_SERVICE_ROLE_KEY` server-only.

bash

```
cp .env.example .env

# Supabase (API + dashboard build):
SUPABASE_URL=https://<your-project>.supabase.co
SUPABASE_KEY=<anon-or-publishable-key>
SUPABASE_SERVICE_ROLE_KEY=<service-role-key> # server-only; never expose in client code
REVIEWER_API_TOKEN=<long-random-string>
SHARE_TOKEN_SECRET=<long-random-string>

# client (landing build-time):
VITE_API_BASE=https://<your-app-url>/api
```

**SUPABASE\_SERVICE\_ROLE\_KEY**, **REVIEWER\_API\_TOKEN**, and **SHARE\_TOKEN\_SECRET** are sensitive — rotate them periodically and never commit or expose them to client code. The two application tokens should be long random strings (32+ bytes).

## 3\. Apply the schema

The Drizzle schema lives in `db/schema.ts`; migrations are committed under `db/migrations/`. Run them once before your first deploy.

bash

```
bun run db:migrate
```

`deploy-build` runs `db:migrate` automatically on each deploy, so subsequent schema bumps apply themselves.

## 4\. Deploy

### On Vercel

bash

```
vercel deploy        # preview
vercel --prod        # production
```

`vercel.json` sets `buildCommand` to `bun run deploy-build`, which typechecks, builds the landing app and dashboard into one output, and applies pending migrations.

### On another runtime

The relevant outputs are:

*   `apps/landing/dist/` — static landing page.
*   `apps/landing/dist/dashboard/` — static dashboard SPA (build with `bun run build:dashboard`).
*   `api/` — Vercel-style serverless handlers using `@vercel/node`. Adapt them to your platform if needed.

## 5\. Smoke test

bash

```
curl -s "$APP_URL/api/v1/public/comments?projectKey=demo-project"
# → [] on a fresh DB, or seeded comments if you ran `bun db:seed`
```

You should get a JSON response. If you ran `bun db:seed`, a `demo-project` row already exists for testing the widget end-to-end.

## Updates and versioning

`crrt.ai` runs whatever is on `trunk`. If you self-host, you can pin to a release tag (`git checkout v0.x.y`) for stability. We aim to keep the public API surface backward-compatible across minor versions. The Drizzle migrations are idempotent, so re-running `bun run db:migrate` after a fetch is safe.

## Going further

**Custom branding** — replace the assets in `apps/landing/public/` and tweak `branding/crrt/tokens.css` if you want to white-label.

**Custom auth** — the dashboard uses Supabase Auth out of the box. Swap `apps/dashboard/lib/supabase.ts` and `api/_lib/auth.ts` if you need a different provider.

**Issues, questions, contributions** — open them on the GitHub repo. We track every one.
