Local Development
How to run VERA on your machine, including the CSS/design-token build step.
Prerequisites
- Node.js (the version Railway runs; an LTS ≥ 18 is safe) and npm.
- PostgreSQL — a local instance or a Supabase/hosted connection string. VERA is Postgres-only; there is no SQLite/in-memory fallback for running the app (tests mock the DB, so tests need no database).
- An Anthropic API key (only needed if you want box-2 / model-backed replies to work; box-1 deterministic paths and the console run without it).
1. Install
bash
git clone https://github.com/talktalkmake/VERA.git
cd VERA
npm install2. Environment variables
Create a .env file in the repo root. The full list and meaning of every variable is in CLAUDE.md under Required env vars; the minimum to boot locally:
bash
ANTHROPIC_API_KEY=sk-ant-... # optional locally; required for model replies
PORT=3000
ADMIN_SECRET=some-long-random-string # gates /admin and /status
TENANTS_FILE=./tenants.dev.json # default; the dev tenant config
DATABASE_URL=postgres://... # runtime role (vera_app in prod)
MIGRATION_DATABASE_URL=postgres://... # privileged role for migrations; in dev set = DATABASE_URL
# Web console (/console) — required or /console* returns 503:
CONSOLE_SESSION_SECRET=$(node -e "console.log(require('crypto').randomBytes(32).toString('hex'))")
CONSOLE_BASE_URL=http://localhost:3000
# OAuth login (optional locally; without it the console login page has no provider button):
# GOOGLE_OAUTH_CLIENT_ID=...
# GOOGLE_OAUTH_CLIENT_SECRET=...Do not set
ERROR_REPORTER_ENABLEDin dev — it must stay off outside production (it files GitHub issues).NODE_ENV=testshort-circuits it during tests regardless.
Tenant config (Slack tokens, audit channel, timezone per tenant) lives in tenants.dev.json. See TENANTS.md for the shape; you can edit tenants in-browser at /admin once running.
Rotating any of these secrets (on compromise, offboarding, or a periodic cadence)? Follow the secret rotation runbook.
3. Database & migrations
VERA uses node-pg-migrate. Apply the schema before first boot:
bash
npm run migrate:up # applies pending migrations against MIGRATION_DATABASE_URL
npm run migrate:down # roll back the last migration
npm run migrate:create my_migration # scaffold a new migration fileIn production, npm start (via scripts/start.js) runs migrate up automatically before booting. Locally, run migrate:up yourself after pulling new migrations.
Why two database URLs?
migrations/0016_app_role.jssplits roles: the privileged role (MIGRATION_DATABASE_URL) can create tables and manage migration bookkeeping; the runtime role (DATABASE_URL→vera_app,NOBYPASSRLS) only hasSELECT/INSERT/UPDATE/DELETE. With a single local role, point both at the same connection string.
4. Run the app
bash
npm run dev # nodemon — auto-reloads index.js on change
# or
npm start # production entrypoint: runs migrations (if MIGRATION_DATABASE_URL set) then index.jsThe app serves Slack (Socket Mode), the internal MCP server, the web console at http://localhost:3000/console, /admin, and /status.
5. CSS / design tokens (build step)
public/tokens.css is a generated, committed artifact — never edit it by hand. It is produced from the single source of truth, docs/design/design-tokens.md:
bash
npm run build:tokens # docs/design/design-tokens.md → public/tokens.cssHow it flows:
docs/design/design-tokens.mdis a markdown table of tokens (color.brand,font.headline,radius.lg, …). It is the only file you edit to change the palette/typography/spacing.scripts/build-tokens.jsparses that table and regeneratespublic/tokens.css, emitting each token as a--vera-*CSS custom property. Colours are emitted twice:--vera-color-x-hsl(theH, S%, L%channels, for composing translucency) and--vera-color-x(the opaquehsla(...)).- The web console links the generated file via
<link rel="stylesheet" href="/static/tokens.css">(served frompublic/), so console styles readvar(--vera-*). - getvera.site (the VitePress docs site) imports the same file via
docs/.vitepress/theme/tokens.css, which maps a subset of VERA tokens onto VitePress's brand variables.
Workflow whenever you change a token: edit docs/design/design-tokens.md → run npm run build:tokens → commit both the .md and the regenerated public/tokens.css. There is a test (tests/design-tokens.test.js) that fails if public/tokens.css is out of sync with the markdown, so a stale build is caught by npm test.
6. Tests
bash
npm test # full Jest suite (~5s, no external services — the DB and Slack are mocked)Tests require no database or API keys. CI/local note: a couple of model-backed simulator tests can flake on the live model; "no non-flaky failures" is the green bar.
7. Docs site (getvera.site)
The public docs site is VitePress under docs/:
bash
npm run docs:dev # local preview of getvera.site with hot reload
npm run docs:build # production build (also syncs the book outline)
npm run docs:preview # serve the production build locallyDocs deploy automatically to https://getvera.site when changes under docs/** land on main.
Script reference
| Command | What it does |
|---|---|
npm run dev | Run the app with nodemon auto-reload |
npm start | Production entrypoint (migrations + app) |
npm test | Jest suite |
npm run migrate:up / :down / :create | Postgres migrations |
npm run build:tokens | Regenerate public/tokens.css from design-tokens.md |
npm run docs:dev / :build / :preview | VitePress docs site |
npm run sync:book | Sync the book outline into the docs build (/about chapters) |