Prerequisites
| Tool | Version | Install |
|---|---|---|
| Node.js | 20+ (LTS) | nodejs.org or nvm install 20 |
| pnpm | 10+ | npm install -g pnpm@10 |
| Docker | Desktop or OrbStack | docker.com or orbstack.dev |
| Wrangler CLI | 4+ | npm install -g wrangler |
Tip:
OrbStack is recommended over Docker Desktop on macOS. It starts faster, uses less memory, and
handles the TigerBeetle io_uring requirement with fewer issues.
Docker Compose Services
Start all infrastructure services with a single command:Service Reference
| Service | Image | Port | Purpose |
|---|---|---|---|
| Postgres | pgvector/pgvector:pg17 | 5432 | Primary database (Neon-compatible) |
| TigerBeetle | Custom (see infra/docker/tigerbeetle/) | 8080 | Double-entry accounting ledger |
| Valkey | valkey/valkey:8-bookworm | 6379 | KV cache / session store (Redis-compatible) |
| SpiceDB | authzed/spicedb:v1.38.1 | 50051 (gRPC), 8443 (HTTP) | Zanzibar-style RBAC authorization |
| Grafana | grafana/grafana:latest | 3333 | Monitoring dashboards |
| Metabase | metabase/metabase:latest | 3334 | BI / SQL analytics |
| Documenso | documenso/documenso:latest | 3335 | E-signature workflows |
| Drizzle Studio | ghcr.io/drizzle-team/gateway:latest | 4983 | Visual database browser |
| Mailpit | axllent/mailpit:latest | 8025 (UI), 1025 (SMTP) | Email capture and testing |
Connection Strings
Once services are running, use these connection strings in your.env:
Service Management
Service Details
Postgres runs with pgvector enabled (Postgres 17). An init script atinfra/docker/postgres-init.sql creates the openinsure and documenso databases on first start. Data persists in the pg_data Docker volume.
TigerBeetle runs in single-replica mode with a custom Docker build (infra/docker/tigerbeetle/Dockerfile). It requires privileged: true for io_uring support. The HTTP API proxy on port 8080 matches the interface the API workers expect in production.
SpiceDB runs with an in-memory datastore (no persistence). The schema is loaded from packages/auth/spice/schema.zed. The gRPC preshared key is localdev.
Mailpit captures all outbound SMTP on port 1025. Open http://localhost:8025 to view captured emails (OTP codes, policy documents, notifications).
Environment Configuration
-
Copy the root
.env.example: -
Copy the API worker dev vars:
-
Set required variables in
.env: -
Match
.dev.varsto your.env(especiallyAPI_SECRET,JWT_SECRET, and DB connection).
Key Environment Variables
| Variable | Description |
|---|---|
DATABASE_URL | Postgres connection string (used by Drizzle migrations) |
JWT_SECRET | API JWT signing secret (min 32 chars) |
API_SECRET | System bearer secret for machine/demo flows |
SERVICE_SECRET | Service token exchange secret |
PORTAL_SECRET | Producer portal token exchange secret |
ADMIN_SECRET | Admin token exchange secret |
AUTH_URL | Auth Worker base URL |
CLOUDFLARE_ACCOUNT_ID | Required for Wrangler and deploy tooling |
CLOUDFLARE_API_TOKEN | Required for Wrangler and deploy tooling |
Database Setup
Run Migrations
Seed Rating Data
Generate Schema Types
After modifying schemas inpackages/db/src/schema/:
D1 (Underwriting Workbench)
The underwriting workbench uses a separate Cloudflare D1 database (oi-submissions):
Drizzle Studio
Openhttp://localhost:4983 in your browser. The master password is localdev.
Make Commands
TheMakefile in the repo root provides shortcuts for common operations:
Development
| Command | Description |
|---|---|
make dev | Start all dev servers (Turborepo) |
make dev-api | Start API worker only |
make dev-workbench | Start underwriting workbench only |
make dev-portal | Start policyholder portal only |
make dev-producer | Start producer portal only |
make dev-admin | Start admin dashboard only |
Quality
| Command | Description |
|---|---|
make test | Run all tests (pnpm turbo test) |
make test-api | Run API tests only |
make test-watch | Vitest watch mode |
make test-coverage | Run tests with V8 coverage enforcement |
make lint | Lint check (Biome) |
make format | Auto-fix lint (Biome, no formatting — oxfmt owns formatting) |
make typecheck | Type-check all packages |
make ci | Full local CI: lint + typecheck + test + pages build |
Database
| Command | Description |
|---|---|
make db-migrate | Run database migrations |
make db-generate | Generate Drizzle schema types |
make db-seed | Seed rating data |
Build & Deploy
| Command | Description |
|---|---|
make build | Build all packages and apps |
make ship | Commit, push, and deploy all apps |
make ship-api | Deploy API worker only |
make ship-workbench | Deploy underwriting workbench only |
make clean | Remove build artifacts and caches |
Dev Server Ports
When runningmake dev, each app starts on its own port:
| App | URL | Filter |
|---|---|---|
| API Worker | http://localhost:8787 | apps/api |
| Underwriting Workbench | http://localhost:3000 | apps/underwriting-workbench |
| Producer Portal | http://localhost:3001 | apps/producer-portal |
| Admin Dashboard | http://localhost:3002 | apps/admin |
| Policyholder Portal | http://localhost:3003 | apps/portal |
| Ops Workbench (Vite SPA) | http://localhost:5173 | apps/workbench |
| Astro Docs | http://localhost:4321 | apps/docs |
| Finance Portal | http://localhost:3006 | apps/finance-portal |
| Compliance Portal | http://localhost:3007 | apps/compliance-portal |
Formatting & Linting
OpenInsure uses two tools with distinct responsibilities:- oxfmt — authoritative code formatter (Rust-based, Prettier-compatible). Config:
.oxfmtrc.json. - Biome — linter only (formatter disabled). Config:
biome.json.
Git Hooks (Husky + lint-staged)
On every commit, Husky runs:biome check --write— lint auto-fixoxfmt --write— formatting (runs last, gets final word)- Credential check — blocks
.env, secrets, API keys - No-any check — blocks
anytype usage
Getting a Dev JWT
For local API testing, exchangeAPI_SECRET for a short-lived superadmin JWT:
Troubleshooting
TigerBeetle fails to start
TigerBeetle requiresio_uring which needs privileged: true in the Docker Compose config. On OrbStack this works automatically. On Docker Desktop for Mac, ensure you have the latest version and that the Linux VM has sufficient resources (4 GB+ RAM recommended).