Skip to content

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 install

2. 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_ENABLED in dev — it must stay off outside production (it files GitHub issues). NODE_ENV=test short-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 file

In 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.js splits roles: the privileged role (MIGRATION_DATABASE_URL) can create tables and manage migration bookkeeping; the runtime role (DATABASE_URLvera_app, NOBYPASSRLS) only has SELECT/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.js

The 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.css

How it flows:

  • docs/design/design-tokens.md is 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.js parses that table and regenerates public/tokens.css, emitting each token as a --vera-* CSS custom property. Colours are emitted twice: --vera-color-x-hsl (the H, S%, L% channels, for composing translucency) and --vera-color-x (the opaque hsla(...)).
  • The web console links the generated file via <link rel="stylesheet" href="/static/tokens.css"> (served from public/), so console styles read var(--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 locally

Docs deploy automatically to https://getvera.site when changes under docs/** land on main.

Script reference

CommandWhat it does
npm run devRun the app with nodemon auto-reload
npm startProduction entrypoint (migrations + app)
npm testJest suite
npm run migrate:up / :down / :createPostgres migrations
npm run build:tokensRegenerate public/tokens.css from design-tokens.md
npm run docs:dev / :build / :previewVitePress docs site
npm run sync:bookSync the book outline into the docs build (/about chapters)