Local setup
Clone, install, start infrastructure, migrate the database, seed data, and run the apps.
These steps take you from a fresh clone to a running app with a working sign-in.
Install dependencies
corepack enable
pnpm installConfigure environment
Copy the example file and fill in values. At minimum you need DATABASE_URL and
BETTER_AUTH_SECRET; the local defaults in the example already match the Docker services.
cp .env.local.example .env.localSee Environment variables for the full reference.
Start local infrastructure
docker compose up -dThis starts PostgreSQL on :6432 and MinIO on :9000 / :9001.
Apply database migrations
pnpm --filter @repo/database migrateThis runs the ordered Drizzle migrations (drizzle-kit migrate). Use this command, not
drizzle-kit push, so local and deployed schemas stay consistent.
Seed an admin + test organization (optional)
pnpm --filter @repo/scripts seed:e2eThe seed is idempotent and additive, so it never truncates data. It creates a platform-admin
user, a full-plan organization (E2E Test Fund), and an owner membership linking them. See
Signing in for the credentials.
Run the apps
pnpm devTurborepo starts every app. For just the product:
pnpm --filter saas devThe app is then available at http://localhost:3000.
Useful scripts
| Command | What it does |
|---|---|
pnpm dev | Run all apps in development (Turborepo). |
pnpm --filter saas dev | Run only the product app on :3000. |
pnpm --filter docs dev | Run this documentation site on :3002. |
pnpm --filter saas type-check | Type-check the product app. |
pnpm --filter @repo/database studio | Open Drizzle Studio to browse the database. |
pnpm test | Run unit tests (Vitest) across the monorepo. |
pnpm lint / pnpm format | Lint with oxlint / format with oxfmt. |
The database scripts (migrate, studio) load their connection string from the repo-root .env
file. Make sure DATABASE_URL is set there, not only in .env.local.