Local development
Ports, every environment variable, a local SSO, the database, peers, and the checks to run before handing work over.
EvalBook runs locally as three processes from one repository: the API, the worker and the web app. Development and tests use SQLite files; production uses one PostgreSQL database. Node 24 is required (nvm use 24.19.0).
You need a Bookbag SSO to sign in to, and it must be a local one, never production: see The local e2e SSO. Organizations, people and roles are managed there; EvalBook reads them live, and platform administration follows SSO's per-product role for EvalBook.
Quick start
source ~/.nvm/nvm.sh && nvm use 24.19.0
npm install && npm install --prefix nextjs-app
# write .env.local (gitignored) as the table below describes
npm run bootstrap # tables for every context (fresh database)
npm run dev # API on :8086
npm run worker # jobs and deliveries (second terminal)
npm run dev --prefix nextjs-app # web on :3006 (third terminal)
Ports
| Process | Port | Command |
|---|---|---|
| API | 8086 (EVALBOOK_HTTP_PORT overrides) |
npm run dev |
| worker | none | npm run worker |
| web | 3006 | npm run dev --prefix nextjs-app |
| tests | 0 (the OS picks) | npm test, npm run test:e2e |
On a machine shared with the sibling products, never bind their ports: 8083, 3003, 8090, 3200, 8081, 3100, 3000, 18080, 18090 and 8080. npm start in nextjs-app binds 3000 and is for the container only.
Environment
npm run dev, npm run worker and npm run seed read .env.local, which is gitignored. The development environment file holds the shape and the non-secret defaults; the variables below win over it. Never commit a value.
| Variable | Needed for | Notes |
|---|---|---|
SSO_ORIGIN |
everything that talks to SSO | Set it. Unset, the server addresses the production SSO. Local e2e SSO: http://localhost:8290 |
SSO_ISSUER |
sign-in | only when the issuer differs from SSO_ORIGIN |
SSO_APP_TOKEN |
sign-in, organization reads, AI, files, billing, peer directory | issued by SSO's app registry (the e2e SSO writes it to tokens.env) |
SSO_UI_ORIGIN |
links to SSO pages the API builds | set it when the SSO UI and API are on different ports (e2e: http://localhost:3290) |
EVALBOOK_ENCRYPTION_KEY |
secrets at rest | 32 bytes as 64 hex characters or base64. Without it, storing a secret throws and /ready fails the encryption check |
EVALBOOK_APP_URL |
links EvalBook writes (peer links, emails) | default http://localhost:3006 |
EVALBOOK_ALLOWED_ORIGINS |
CORS beyond http://localhost:3006 |
comma-separated |
EVALBOOK_INLINE_WORKER=1 |
running jobs inside the API process | for tests and quick local runs; normally run npm run worker |
PEER_SECRET, PEER_CODEBOOK_URL, PEER_MADEBOOK_URL, EVALBOOK_PUBLIC_API_URL |
local peer overrides | replace SSO's peer directory for local work; their names are logged at boot, never their values |
EVALBOOK_PRIVATE_HOSTS |
letting outbound calls reach named local hosts | e.g. localhost:8283 for a local CodeBook; private addresses are refused otherwise |
EVALBOOK_DIAGNOSTICS_TOKEN |
/ready detail for a monitor |
optional, at least 32 characters |
LOG_LEVEL |
logging | debug, info (default), warn, error |
JOB_POLL_MS, OUTBOX_SCHEDULE_MS, RETENTION_FIRST_MS, JOB_CONCURRENCY_<QUEUE> |
worker timing | defaults suit production |
EVALBOOK_DB_HOST, _PORT, _NAME, _USER, _PASSWORD, _SSL, _SSL_INSECURE |
PostgreSQL (container) | turned into the connection override at container start |
Generate the encryption key straight into the file without printing it:
printf 'EVALBOOK_ENCRYPTION_KEY=%s\n' "$(node -e "process.stdout.write(require('crypto').randomBytes(32).toString('hex'))")" >> .env.local
The web app reads nextjs-app/.env.local: NEXT_PUBLIC_SSO_ORIGIN is the SSO UI origin for sign-in, sign-out and account links (set it; e2e SSO: http://localhost:3290; unset means production), API_ORIGIN is where /api/* is proxied (default http://localhost:8086), and NEXT_DIST_DIR is the build output directory.
Database
- Fresh database:
npm run bootstrapcreates every table from the current entities in every context; safe to re-run, it adds missing tables and columns only. - Migrations:
npm run migrateapplies pending ones in every context. - SQLite files live in
db/and are gitignored. To start over, stop the API and worker and move them aside. - Data:
npm run seed -- --org <SSO org id> --admin <member email> --project "<name>"creates one real project through the same service the UI uses. There is no demo data.
Peers
CodeBook and MadeBook find EvalBook through SSO's peer directory. For a local pair, run their feat/evalbook worktrees against the e2e SSO (CodeBook on 3283/8283, MadeBook on 3281/8281). See Peer links.
Checks before handing work over
npm test # unit tests, authorization coverage (0 unprotected), cookie isolation
npm run test:e2e # the real API over HTTP on port 0 against a fake SSO and fake peers
cd nextjs-app && npm run build:check; echo $? # 0; builds into .next-check, safe while next dev runs
npx eslint .
The fake SSO and fake peers in test/support/ are declared test doubles, never used outside tests.