REACTOME is an open-source, open access, manually curated and peer-reviewed pathway database.
npm ci
npm startnpm start builds the workspace libraries and stages content first, so there are
no manual steps before it. It serves the development deployment, which
resolves its own origin and reaches the backend through the dev-server proxy.
That proxy points at http://localhost:8080 by default, because on the Reactome
dev host the whole stack runs there and answering locally is ~2ms against ~17s
out through Cloudflare and back. On a machine without that stack — any laptop —
point it somewhere real instead, or every API call is refused and you get a
shell with no data:
REACTOME_BACKEND=https://dev.reactome.org npm startWhat each deployment needs locally:
| command | backend it uses | needs anything running? |
|---|---|---|
npm start |
the proxy, i.e. REACTOME_BACKEND |
a backend at :8080, or the variable set |
ng serve -c curator |
newcurator.reactome.org | no |
npm run start:curator-local |
localhost:8686 for the graph API |
a local curator-service |
npm run start:simple |
same as npm start, skipping TinaCMS |
as above |
The curator deployment is the one that needs nothing running locally, so it is the quickest way to check a clone works at all.
Content editors want npm start, which runs TinaCMS alongside the app. No
credentials are needed for local editing — the .env file is only a UID mapping
for the Docker workflow below.
docker compose upThe container writes into your working copy — the build cache, the staged
content, TinaCMS's generated client — so it runs as an unprivileged user rather
than root, or those files come back owned by root and your own ng build then
fights the container for .angular/cache.
That user's ids default to 1000:1000, which is what a stock Linux install
gives the first account, and Docker Desktop on macOS and Windows maps ownership
for you regardless. If id -u says anything else, point the build at your ids
once and rebuild:
printf 'UID=%s\nGID=%s\n' "$(id -u)" "$(id -g)" > .env
docker compose build && docker compose up -d.env is not committed, so each machine sets its own. Changing it needs
docker compose down -v as well, because the anonymous node_modules volume
keeps whatever ownership it was first created with.
Reactome has a wide range of features, to explore more of Reactome or get more information visit the documentation page or see the /documentation folder in the root directory.
Four libraries live in this repo under projects/ and build to dist/. The apps consume them from there (via the dist/ entry in each project's stylePreprocessorOptions.includePaths, and the paths mappings in tsconfig.json), not from node_modules — so they must be built before the app will compile:
| project | contents |
|---|---|
reactome-cytoscape-style |
diagram rendering styles + drawing helpers |
ngx-reactome-style |
shared Angular Material theme (Sass only, no TypeScript) |
reactome-table |
the editable data grid |
reactome-gsa-form |
the ReactomeGSA analysis wizard (NgRx-backed) |
npm start builds them for you. To build them by hand:
npm run build:libs # ngx-reactome-style, reactome-table, reactome-gsa-form
ng build reactome-cytoscape-style # or `npm run dev:reactome-cytoscape-style` to watchThe last three were previously separate npm packages (reactome-gsa-form, reactome-table and reactome-table-wc from reactome/gsa-frontend; ngx-reactome-style published standalone). They were absorbed here so their Angular/NgRx peer dependencies stay in lockstep with the rest of the workspace instead of pinning it to an older major. They can still be published to npm from this repo — build, then npm publish dist/<name>.
The application configuration is centralized in TypeScript files under projects/website-angular/src/config/. Key configurations include:
config.ts: App-level settings like version, base URLs, and feature flags.environments.ts:SITE_PROFILES— one row per deployment, naming both the backend it talks to and the UI variant it presents. See "Deployments" below.features.ts: Feature flags for toggling functionality.external-links.ts: External links, including dynamically constructed release notes.
To update configuration values, edit the respective TS files.
The single source of truth for backend URLs (CONTENT_SERVICE, ANALYSIS_SERVICE, DOWNLOAD, etc.) is projects/pathway-browser/src/environments/environment.ts — imported by both pathway-browser and website-angular code. Don't duplicate these constants elsewhere; if a page needs a backend URL, import it from here.
One name chooses everything about a deployment: which backend it talks to and
which UI it presents. The list lives in projects/website-angular/src/config/environments.ts
as SITE_PROFILES, one row per deployment, and the APP_ENV define in
angular.json picks the row.
| deployment | backend | UI | analytics |
|---|---|---|---|
production |
its own origin (falls back to reactome.org off-browser) | main | reports |
beta |
its own origin (falls back to beta.reactome.org) | main | none |
development |
its own origin (falls back to dev.reactome.org) | main | none |
curator |
newcurator.reactome.org, /GraphContentService |
curator | none |
curator-local |
graph API on localhost:8686, rest from newcurator |
curator | none |
Analytics is a profile field, and only production names a property. Every
other deployment leaves it unset, which means gtag is never loaded and nothing is
sent — beta, dev and the curator site report nothing at all. Sending their hits
to the public property would inflate reactome.org's numbers with traffic it never
received, and no one reading those numbers later could separate the two.
The trade-off worth knowing: nothing outside production exercises the analytics path, so the first real run is on reactome.org. To check the wiring before then, give a non-production profile a property temporarily, or use GA4's DebugView — don't leave one set.
The public deployments resolve window.location.origin rather than naming a
host, and that matters: beta.reactome.org reverse-proxies its own
/ContentService to the Tomcat on its box, and that Tomcat serves endpoints the
public one does not -- the reaction-diagram exporter among them. A build that
names reactome.org instead loads fine and then fails to draw its reaction
diagrams. A site talks to itself; the fallback applies only where there is no
window (SSR, unit tests).
npm start # public site, dev backend
npm run start:curator # curator site
npm run start:curator-local # curator site, local graph service
npm run build # bundle for beta/reactome.org
npm run build:curator # bundle for the curator hostAdding a deployment -- Plant Reactome, say -- is a row in SITE_PROFILES plus
whatever UI genuinely differs. It is not a new environment file, and it should
not be a new boolean.
Two rules the design exists to enforce:
- No profile may name another deployment's services, fallbacks included. A
fallback that reaches a different deployment renders someone else's data
without saying so.
getProfile()also throws on a name it does not recognise rather than guessing, because guessing is how the curation database came to be served from beta.reactome.org. environment.tsis the single source of backend URLs (CONTENT_SERVICE,ANALYSIS_SERVICE,RENDER_SERVICE,DOWNLOAD, ...). Import them; do not rebuild one fromhostat a call site.
IS_CURATOR (from environment.ts) is how UI branches on the variant today --
@if (!isCurator) / @if (isCurator), see viewport.component.ts. When a third
variant arrives, switch on the variant itself rather than adding a second
boolean.
npm run start:curator-local serves the curator UI with the graph content API on
http://localhost:8686. A locally run content service is a bare Spring Boot app,
so its routes sit at the root (/data/query/...) rather than under a
/GraphContentService context path -- which is why contentService is a
separate field from host. Everything it cannot serve is proxied through
proxy.curator-local.conf.json, because newcurator.reactome.org/download sends
no Access-Control-Allow-Origin.
Expect one console error on startup: data/database/version 500s on a curation
graph, which has no released version. That is the versionFallback in the
profile doing its job, not a misconfiguration.
deploy.yml runs after a green Tests run and publishes to S3 under a release
number it computes at build time — not under a fixed path:
| branch | published to | what it is |
|---|---|---|
main |
<current release + 1>/website/ |
the next release's artifact |
prod |
<current release>/website/ |
the current release's artifact |
The current release comes from reactome.org/ContentService/data/database/version
at build time. So a push to main today lands in /98/website/ while /97/website/
holds whatever prod last published — which may be months old, and correctly so.
npm run deployed prints both URLs with their timestamps. Use it before checking
a published artifact: reading the aws s3 sync line in the workflow suggests one
path and the version step above it decides another, and a day of verification was
once aimed at the stale one as a result.
A published artifact is served from the bucket, which has no backend of its own,
so it reaches the host named in SITE_PROFILES.production rather than its own
origin. That is why production is the one deployment that names a host instead
of resolving 'origin'.
beta serves dist/reactome/browser straight from this checkout, so building is
deploying. ~/rebuild-beta.sh does it with a dirty-tree guard and a smoke
test; ~/rebuild-beta.sh --check reports whether what beta serves matches what
is on disk.