This document is for people working on the Neuromorphic Job Manager web app
itself. For an overview of the app and its place in the EBRAINS Neuromorphic
Computing service, see README.md. For how the pieces fit
together at runtime, see architecture.md. For deployment,
see operations.md.
- Node.js 20.x (the version used in CI and in the production Docker image).
- npm.
- An EBRAINS account if you want to log in against the real services.
git clone https://github.com/HumanBrainProject/nmpi-job-manager-app.git
cd nmpi-job-manager-app
npm ci
sh scripts/install-hooks.sh # installs the JWT-leak pre-commit hooknpm run devThis serves the app at http://localhost:3000 with hot-reload.
By default src/globals.ts points the dev server at a local Job Queue API
(http://localhost:8000) and at the integration IAM
(https://iam-int.ebrains.eu, client neuromorphic-remote-access-dev). If you
don't have a local backend running, edit src/globals.ts to point at the
deployed API:
export const jobQueueServer = "https://nmpi-v3.hbpneuromorphic.eu";
export const authServer = "https://iam.ebrains.eu";
export const authClientId = "neuromorphic-remote-access";(These match src/globals-staging.ts — which currently targets the
production Job Queue API while the staging API is being deployed; the
production build values are in src/globals-prod.ts. The Docker builds swap one
of these in over globals.ts at build time — see
operations.md.)
Do not commit changes to globals.ts.
Two options:
- Full Keycloak login flow — just open the dev server; you'll be
redirected to IAM. This works against
iam-int.ebrains.euif you have an integration account, oriam.ebrains.eufor prod/staging. - Paste an existing IAM token — copy
.env.local.exampleto.env.localand paste a token intoVITE_DEV_TOKEN.src/main.tsxskips the Keycloak flow whenVITE_DEV_TOKENis set. Useful when iterating on UI without constantly re-logging in.
The pre-commit hook in scripts/pre-commit blocks any commit whose diff
contains a JWT-shaped string, to keep tokens out of git.
src/
main.tsx entrypoint: theme, router, context providers, auth bootstrap
auth.ts Keycloak init (standalone / iframe-Collab / delegate-tab flows)
datastore.ts all REST calls to the Job Queue API + a small in-memory cache
context.ts React contexts: Auth, Status, RequestedCollab
types.ts shared TypeScript types (API shapes, Auth, …)
utils.ts small helpers (jobIsIncomplete, isAlmostEmpty, …)
globals.ts dev defaults — overwritten at build time
globals-prod.ts production endpoints (used by Dockerfile.prod)
globals-staging.ts staging endpoints (used by Dockerfile.staging)
vite-env.d.ts Vite / import.meta.env type declarations
index.css global styles
components/
general/ shared UI: AppBar, ErrorPage, MarkdownPanel, …
home/ landing page
jobs/ job list page
job-detail/ single-job view (logs, comments, outputs, tags)
job-creation/ new-job form and "edit & resubmit"
projects/ per-collab project (quota) list
admin/ admin-only resource-request review (merged-in admin app)
routes/ one file per React-Router route; exports element + loader/action
__tests__/ mirrors src/ — vitest + @testing-library/react; fetch is mocked
deployment/ Dockerfiles, nginx configs, docker-compose stubs
scripts/ git-hook installer + pre-commit JWT scan
public/ static assets served at /
tsconfig.json TypeScript compiler options (strict)
vite.config.ts Vite + Vitest configuration
npm test # watch mode
npm run coverage # one-shot run with v8 coverage; this is what CI runsConventions:
- Tests use Vitest, configured in
vite.config.ts. __tests__/setup.tswires upvitest-fetch-mocksofetchis mocked by default. Tests that need a custom response usefetch.mockResponseOnce(...).__tests__/mockServer.tsprovides a fixture-backed fake Job Queue API (using the fixtures in__tests__/fixtures.ts) for tests that exercise several endpoints at once.- New components should ship with at least a render-smoke test under
__tests__/components/<feature>/.
There are currently no integration tests against the real Job Queue API. Adding at least one staging-side smoke test is tracked as a GitLab issue.
npm run lintnpm run lint runs eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0. The CI build runs the same command, so any warning fails the
build. Configuration:
.eslintrc—eslint:recommendedplus the React and React-Hooks plugins, with a*.ts/*.tsxoverride pulling in@typescript-eslint/recommended..prettierrc.json— 2-space tabs, 112-char width, ES5 trailing commas.
It is recommended to run Prettier-on-save in your editor. There is no project-wide pre-commit formatter; rely on the editor + CI lint.
npm run typecheck # tsc --noEmitnpm run build runs the same tsc --noEmit pass before vite build, so a type
error fails the build (and therefore CI). Compiler options are in
tsconfig.json (strict mode); shared types live in src/types.ts.
- Create the React component(s) under
src/components/<feature>/. - Create the route file under
src/routes/<name>.tsx. Export a default element component and (if it needs server data) agetLoaderfactory and (if it accepts form submissions) anaction. Match the patterns insrc/routes/jobs.tsxandsrc/routes/job-detail.tsx. - Register the route in
getRouter(keycloak)insrc/main.tsx. - If the page calls the Job Queue API, add the call to
src/datastore.ts(don't bypass it — the cache lives there), with any new request/response shapes typed insrc/types.ts. Update__tests__/datastore.test.ts. - Add tests under
__tests__/components/<feature>/.
npm updatefor patch/minor bumps inside the existing semver ranges.- For major bumps, change the range in
package.json, runnpm install, run the test suite, and commitpackage.json+package-lock.jsontogether. - Dependabot is enabled on the GitHub repo for security updates.
- Merge the change to
master(CI green). - Merge
master→staging, verify on the staging deployment. - Decide the next Semantic Version
X.Y.Z— a patch, minor, or major bump relative to the most recent tag, depending on the change. - Update
CHANGELOG.md: move items out of[Unreleased]into a new[X.Y.Z] — YYYY-MM-DDsection. - Bump
package.json'sversionfield toX.Y.Z. - Commit, then tag:
git tag vX.Y.Z && git push --tags. - The push triggers the GitLab CI build of
:prodand:stagingDocker images. Deployment is managed via theebrains-componentsrepository.