Local development

Prerequisites

  • Node.js 22 LTS
  • pnpm 9.15 (npm i -g pnpm)
  • Docker (Docker Desktop on macOS/Windows, Docker CE on Linux)

Dev stack (Postgres 16, Redis 7, MinIO, Mailpit)

``bash

one-time: copy and configure env

cp .env.example .env

Generate secure values:

PLATFORM_MASTER_KEY: openssl rand -base64 32

SESSION_SECRET: openssl rand -hex 32

start services

docker compose up -d

stop services

docker compose down

`

Service endpoints:

| Service | Endpoint | Notes |

|----------|----------|-------|

| Postgres | postgres://vercia:vercia@localhost:5432/vercia | tests use vercia_test |

| Redis | redis://localhost:6379 | |

| MinIO | http://localhost:9000 (console :9001) | S3-compatible |

| Mailpit | SMTP :1025, UI http://localhost:8025 | captures all dev mail |

Windows (WSL2)

Docker CE runs inside WSL2 Ubuntu. There is no Docker Desktop and no Windows-side docker CLI. All docker commands run through WSL: wsl -d Ubuntu docker <args>.

WSL2 terminates its VM ~60 s after the last terminal session ends, killing the containers. Use the included helper scripts from PowerShell:

`powershell

./scripts/dev-stack-up.ps1 # starts services + a keep-alive WSL session

./scripts/dev-stack-down.ps1 # stops services + kills the keep-alive

`

Install and typecheck

`bash

pnpm install

pnpm typecheck

`

Tests

Tests are hermetic by default — they use PGlite (in-process Postgres) and in-memory adapters:

`bash

pnpm test # all packages, no Docker required

pnpm build # production build of all packages

`

Real-Postgres integration tests

A small real-Postgres suite (RLS isolation, migrator ledger, outbox/audit durability) is skipped unless TEST_DATABASE_URL is set. With the dev stack up:

`bash

create the test database once

psql "postgres://vercia:vercia@localhost:5432/vercia" -c 'CREATE DATABASE vercia_test'

run the gated suite

TEST_DATABASE_URL=postgres://vercia:vercia@localhost:5432/vercia_test \

pnpm --filter @vercia/database test

`

Or add TEST_DATABASE_URL to your .env to enable it globally.

Running the apps

`bash

pnpm dev # turbo: api, worker, web, admin, control in parallel

`

| App | URL | Command |

|-----|-----|---------|

| API | http://localhost:3001 | pnpm --filter @vercia/app-api dev |

| Web | http://localhost:3000 | pnpm --filter @vercia/app-web dev |

| Admin | http://localhost:3002 | pnpm --filter @vercia/app-admin dev |

| Control | http://localhost:3003 | pnpm --filter @vercia/app-control dev |

| Worker | — (stdout) | pnpm --filter @vercia/app-worker dev |

Environment loading

api and worker call loadDotenv() from @vercia/config at startup — it walks up to the workspace root and loads .env there (real environment variables always win). So pnpm --filter @vercia/app-api dev works without manually exporting the file.

The Next.js apps (web, admin, control) load env via Next.js conventions. Variables needed in the browser must be prefixed NEXT_PUBLIC_.

CLI

`bash

pnpm platform --help # platform CLI

pnpm platform module:create --help # scaffold a new module

pnpm platform catalog:generate # regenerate docs/catalog/

`

Seeding dev data

`bash

pnpm --filter @vercia/seed run # creates the default admin user and a demo tenant

`

Default seed credentials are printed to stdout. Do not use them in production.

Useful checks

`bash

verify no cross-module boundary violations

pnpm --filter @vercia/architecture-tests test

typecheck a single package

pnpm --filter @vercia/module-identity typecheck

run tests for a single module

pnpm --filter @vercia/module-identity test

``