Setup
Prerequisites
- Node.js 22+ (repo is developed on Node 24;
.nvmrcpins 22 for CI/deploy). - npm with workspaces (the lockfile is
package-lock.json).
Install
npm install
A single root install hoists dependencies for every workspace and the documentation tooling.
Develop
The repo is a monorepo; pick an app:
npm run dev tracking # @enode/tracking → http://localhost:3000
npm run dev portal # @enode/portal → http://localhost:3001
npm run help # list all commands
In dev, next.config.ts proxies /api/* to the backend so the browser sees
same-origin requests (no CORS).
Choosing the backend. Which backend the apps talk to is defined in one place,
packages/core/src/api/servers.ts, and
read by both the dev proxy and the runtime API client — so there is no second
place to keep in sync. Switch it with env vars, no code edit:
NEXT_PUBLIC_API_SERVER=<name>— pick a named server fromAPI_SERVERS.NEXT_PUBLIC_API_BASE_URL=<url>— point at any host (a local backend, an ngrok tunnel); wins over the named server.- Neither set → the default (
develop).
Add a new named environment by extending API_SERVERS (and the ApiServerName
union) in that file.
Switching at runtime. In dev, each app's debug area has a Backend switcher
(tracking: /debug/server, portal: /dashboard/debug) that repoints the client
without a restart: it stores the choice in localStorage and reloads. Named
servers go through their own same-origin proxy prefix (/api-<name>); the extra
localhost row takes a port (default 8080) and calls
http://localhost:<port>/api directly — a rewrite destination is fixed when
the dev server boots, so it can't take a port typed in the browser. That makes
localhost the one cross-origin target: the local backend must allow the dev
origin (http://localhost:3000 / :3001) via CORS.
Optional per-machine settings (tracking). A few features read build-time variables that are deliberately not committed. Copy the template and fill in what you need:
cp apps/tracking/.env.local.example apps/tracking/.env.local
Nothing there is required to build or run the app. The one worth knowing about is
NEXT_PUBLIC_QUESTIONNAIRE_BYPASS: without it, the wellness check-in on a dev
build silently does nothing — it closes after about four seconds, because
portaldev sits behind Vercel Deployment Protection and the frame never loads.
That is the designed fail-open, so it looks like a broken feature rather than a
missing credential. The template says where to get the value; see
questionnaire-service.md for the mechanism.
Each app opens on a login gate. Authenticate with backend credentials to reach the main feature.
Repo-wide commands
| Command | What it does |
|---|---|
npm run dev <app> | Dev server for tracking (:3000) or portal (:3001) |
npm run build <app> | Production build → static export in the app's out/ |
npm run run <app> | Serve the built out/ |
npm run lint | ESLint across all workspaces |
npm run test | Vitest unit tests (@enode/core) |
npm run typecheck | tsc over the whole monorepo |
Documentation commands
| Command | What it does |
|---|---|
npm run storybook | Storybook dev server (:6006) |
npm run docs:build | Build the full documentation website |
npm run docs:serve | Serve the built docs site (:4000) |
npm run docs:check | Lint + typecheck + docs build (CI gate) |
See Testing for the docs build/check pipeline.