Local setup
Constellation is a Turborepo monorepo using npm workspaces. Node 20+ required.
Install
git clone https://github.com/B2B-Online/constellation.git
cd constellation
npm install
Start the dev services
The apps need a local PostgreSQL (shared by all modules) and MinIO (for storage).
npm run dev:services # starts PostgreSQL + MinIO in Docker
npm run db:migrate # applies all module and platform-package migrations
db:migrate covers the shared platform packages that own a schema, not just apps/* — @constellation-platform/jobs provisions jobs this way. On a database that already carries jobs.queue from Project Tracker's older migration, the jobs runner adopts its baseline rather than re-applying it, and refuses loudly if the deployed table does not match what the migration declares. See Deployment → Platform packages carry their own migrations.
Run an app
npm run dev:dir # Directory on :3001
npm run dev:pt # Project Tracker on :3002
# or
npx turbo dev --filter=@constellation/catalog
Seed local data
Migrations create empty schemas, so an app started at this point renders empty. Each module ships its own seeders — run them from the repo root:
# Project Tracker
npm run db:seed --workspace=@constellation/project-tracker # baseline reference data
npm run seed:sample --workspace=@constellation/project-tracker -- <org-slug>
npm run seed:stress --workspace=@constellation/project-tracker # large-scale UI perf data
# Wiki
npm run seed:dev --workspace=@constellation/wiki # a small working space
npm run seed:volume --workspace=@constellation/wiki # deterministic volume, --seed to reproduce
npm run workload:concurrent --workspace=@constellation/wiki # drives the wiki under concurrency
seed:volume and workload:concurrent purge and rewrite the spaces they own. Both refuse
any target that is not loopback (localhost, 127.0.0.1, [::1]) — for the database URL and,
for the workload runner, the base URL as well — and there is no --force. Point them at a
developer machine, never at a shared or deployed environment.
The wiki seeds (seed:dev, seed:volume, seed:eval and the review fixture) create their
identity rows — tenant, organisation, users, memberships, role grants — through one audited
bootstrap: each run appends a seed.identity_bootstrapped (or fixture.tenant_provisioned)
entry to the tenant's audit log, recording the rows actually written, and refuses ids another
tenant already owns. So they need the generated wiki Prisma client, a built
@constellation-platform/audit, and migrated audit and events schemas.
The Project Tracker seeds (db:seed, seed:stress) write users, roles, role permissions, role
grants and memberships the same way: audited transactions, one per tenant, that append
seed.identity_principals_seeded and seed.identity_authority_seeded entries recording the rows
actually written. seed:stress
refuses any non-loopback DATABASE_URL, with no --force.
seed:volume is deterministic: the same --seed and the same counts produce the same fixture,
and the run prints the exact arguments needed to reproduce it. The flags, and the constraints
that are not obvious from them, are documented in
apps/wiki/AGENTS.md.
Full CI pipeline locally
Before every push:
npx prettier --check "**/*.{ts,tsx,js,jsx,json,md}"
npx turbo run lint typecheck build test
npm run check:routes
See the root CLAUDE.md for the full checklist.
Per-OS notes
The setup above works on every supported OS — these sections only call out the gotchas that vary.
macOS
Required tooling: node (≥ 20, install via nvm or Homebrew), docker (Docker Desktop or OrbStack), git. Recommended: psql from Homebrew (brew install postgresql@16) — set PSQL_PATH=/usr/local/bin/psql (or /opt/homebrew/bin/psql on Apple Silicon) in your .env.local so module migrations can find it.
If you use OrbStack instead of Docker Desktop, no special configuration is needed — npm run dev:services works against either.
Linux
Required tooling: node (≥ 20), docker + docker compose plugin, git. The dev:services script binds default ports — make sure ports 5432 (Postgres) and 9000 / 9001 (MinIO) are free. If your distro packages psql separately (apt install postgresql-client), no env-var override is needed; the binary is on the default PATH.
Windows / WSL2
The supported workflow is WSL2 with an Ubuntu (or similar) distro, not native Windows + PowerShell. Inside the WSL2 distro the Linux instructions above apply directly. Reasons:
- Module migrations call
psqland rely on POSIX tooling. PowerShell paths break the migration scripts in subtle ways. - Docker Desktop's WSL2 integration gives you
dockeranddocker composefrom inside the distro out of the box. - The repo has been exercised against WSL2 + Ubuntu 22.04+; native Windows is not currently in CI.
If you need to work directly on Windows for some reason, expect to debug shell-script differences yourself — patches welcome but support is best-effort.
Troubleshooting
psqlnot found — on macOS setPSQL_PATH=/usr/local/bin/psql(or/opt/homebrew/bin/psqlon Apple Silicon) in your.env.local.- Migration fails with
P2028/ "Transaction already closed" — the runner wraps each migration file in one transaction, and the default ceiling is 10 minutes (MIGRATION_TX_TIMEOUT_MS). Nothing is half-applied: the file rolls back whole. Hitting it usually means a heavily loaded machine or a remote database rather than a bad migration; retry on a quieter machine, or raise the value in.env.local. - Prisma client out of date — run
npx turbo db:generate. - Port already in use — the dev:services Docker compose binds default ports; stop conflicting processes or edit
docker-compose.dev.yml.