Skip to content

Run OnERP locally

OnERP is a monorepo: an API, an admin app, a warehouse app, and this documentation site. One command starts them all.

Node.js 22 or newer and pnpm 10 — the version is pinned in the root package.json under packageManager, so corepack enable fetches it.

Postgres and Redis, running locally. Any recent Postgres works (Postgres.app, Homebrew, Herd); the API needs a database to point at, and Cube — the analytics engine the dashboard reads — queries that same database over the wire. Redis backs the background jobs and the live updates between open tabs. Without Redis the API and pnpm cli refuse to start with Connection is closed.

Terminal window
pnpm install
createdb onerp
cp apps/api/.env.example apps/api/.env # set DATABASE_URL to your Postgres
cp apps/cube/.env.example apps/cube/.env # same database, same CUBEJS_API_SECRET
pnpm build # workspace packages are consumed from dist/
pnpm cli reset --demo # wipe, migrate, seed a Dev tenant
pnpm dev

pnpm dev starts every app in watch mode:

Admin app http://localhost:5173
Warehouse app http://localhost:5174
API http://localhost:3000
This site http://localhost:4330
Inngest dev server http://localhost:8288
Cube (analytics) http://localhost:4000

Nothing else needs starting. The development tools below are switches on the API rather than servers of their own.

Cube is the analytics engine, and clients query it directly rather than through the API: GET /api/analytics/access returns Cube’s address and a token scoped to the signed-in tenant. Cube’s Playground is on http://localhost:4000 — set a security context of { "tenantId": "…", "modelVersion": "…" } there before running a query, because the compiled data model is per tenant.

await client.cube() returns the authenticated Cube client. React applications query it with useCubeQuery from @onerp/react/data. Dashboard totals come from Cube; record previews use the list API. The dashboard loads totals when opened and does not poll for changes.

Open http://localhost:5173:

email: dev@onerp.dev
password: dev-password
tenant: Dev

The warehouse app takes the same credentials.

pnpm cli reset drops every schema in the configured database, re-runs the migrations, and creates a tenant called Dev. It prompts before wiping anything; pass --yes to skip the prompt.

The tenant is born with its base seed data, the same set a real signup gets: the payment term Net 30, number series for sales orders and sales invoices, a profile called Default with no company yet, the Quality Inspection and Blocked stock restrictions, and every EU country’s VAT rates with the Standard / Reduced / Exempt classifications.

Units of measure are a code list rather than records, so nothing seeds them. No locations are seeded, and no stock can move until some exist.

--demo adds a sample dataset on top: business partners, product types, categories and products, sales prices, sales orders, a warehouse hierarchy with bins, and stock booked into it. The user guides are written against that dataset.

Every optional piece is a line in apps/api/.env, documented in apps/api/.env.example. Set it, restart pnpm dev:

Set in apps/api/.env What it gives
DATABASE_LOG_QUERIES=true every SQL statement, with duration and parameters, in the API log
NEST_DEVTOOLS=true the dependency graph, routes with their guard chains, and bootstrap timings, served on :8000 for Nest Devtools. Structural only — no requests, no queries
AI_DEVTOOLS=true agent tool calls, model input and output, and token usage. Run pnpm ai:devtools alongside and open http://localhost:4983
ANTHROPIC_API_KEY= or OPENAI_API_KEY= the assistant in the admin sidebar. Without one it errors when opened
MAIL_PREVIEW=true outgoing mail opens in the browser instead of reaching an SMTP server. On by default

Request traffic needs nothing enabled — read it in the browser’s Network tab.

pnpm e2e starts its own API, Cube and web servers on separate ports and wipes its database on every run, so it never shares one with development: create onerp_e2e once (createdb onerp_e2e) and the suite derives the connection from DATABASE_URL in apps/api/.env, or set E2E_DATABASE_URL outright.

The unit-test harness is the one place PGlite (Postgres in WebAssembly) still runs; the API accepts DATABASE_DRIVER=pglite for it, and nothing that needs Cube works there.

Command What it does
pnpm dev every app in watch mode
pnpm cli reset --demo wipe, migrate and reseed the Dev tenant
pnpm test the test suites
pnpm e2e Playwright journeys
pnpm type-check · pnpm lint · pnpm format run all three before pushing
pnpm docs:screenshots regenerate the guide screenshots from the real app

Your first resource takes one business object from schema to a working list and form.