Skip to content

Local setup

  • Node.js 20+ (the container image uses 22)
  • pnpm
  • A MongoDB instance — only needed to run Watcher, not to develop against the tests
  1. Install:

    Terminal window
    pnpm install
  2. Run the gate. This needs no keys and no network:

    Terminal window
    pnpm verify

    Typecheck, lint, the full test suite, and a build. If this is green, your environment is correct.

  3. Configure, when you want to run it for real:

    Terminal window
    cp .env.example .env

    Minimum: a Google API key and a MongoDB URI.

  4. Run something:

    Terminal window
    pnpm watches:import
    pnpm run-due:force
Terminal window
pnpm test:watch # tests, re-running on change
pnpm dev # run-due, re-running on change
pnpm serve # the API + scheduler
pnpm verify # the gate, before you commit
Terminal window
AUTH_JWT_SECRET=$(node -e "console.log(require('crypto').randomBytes(32).toString('base64url'))") pnpm serve

Then create an account so you can sign in:

Terminal window
ADMIN_PASSWORD='local-dev-password' pnpm users:create dev@example.com --role admin --id local

With the panel’s dev server running, sign in there.

One test talks to a real database. It self-skips unless you point it at one:

Terminal window
MONGO_TEST_URI="mongodb://localhost:27017" pnpm test:integration

It is excluded from pnpm verify on purpose, so the default gate stays hermetic.

  • Formatting and linting: Biome. pnpm lint:fix and pnpm format are the entry points; there is a single configuration at the repository root.
  • TypeScript: strict, with unchecked-index access enabled. If the compiler complains that an array element may be undefined, it is right.
  • ESM only: relative imports carry a .js extension even in TypeScript sources. That is required, not a mistake.
Symptom Cause
pnpm verify fails on lint after your edit Run pnpm lint:fix; import order is enforced
Tests pass, run-due fails immediately Missing GOOGLE_GENERATIVE_AI_API_KEY or MongoDB_URI
pnpm serve exits at startup Missing or too-short AUTH_JWT_SECRET
The panel loads but every request fails The API is not running, or WEB_ORIGIN does not list the panel
Watches exist in files but not in the app You have not run pnpm watches:import