Contributing to Cellucid (Web App)#
Cellucid is a web app (browser UI + state layer + WebGL renderer) hosted at https://www.cellucid.com.
Where the web-app contribution guide lives#
cellucid/CONTRIBUTING.md, in the cellucid
repository, is the authoritative guide for working on the web app: which
repository a change belongs in, what to put in a bug report, how to run the app
locally, where the code lives, the coding and performance rules, how to run the
tests, and what a good pull request looks like. It ships beside the code it
describes and is the file GitHub shows a contributor when they open an issue or
a pull request, so it is kept self-sufficient.
This page is not a copy of that file, and neither file is generated from the other. It owns the part of web-app contribution that only exists on this documentation site:
Question |
Answer lives in |
|---|---|
Which repository does my change belong in? |
|
How do I report a UI or rendering bug? |
|
How do I run, test, and open a pull request against the web app? |
|
Where does the web app’s code live, and what are the performance rules? |
|
How do I write or change a web-app page on this site? |
this page, below |
Which URL form and version marker do I use across repositories? |
this page, below |
The split is deliberate, not an oversight, and it is not a mirror that fell out
of date. The documentation build tree contains only cellucid-python
(.readthedocs.yaml clones no siblings and declares no submodules), so this
page cannot {include} a file from the cellucid repository the way
Contributing to Cellucid (Python) includes cellucid-python/CONTRIBUTING.md from its own
repository. The choice was therefore between hand-copying content across a
repository boundary — which drifts, silently, because no build or test spans
both repositories — and giving each file one audience and cross-linking. Each
fact below has exactly one home.
I want to work on docs for the web app#
The documentation site is built from cellucid-python/docs/, so a web-app
documentation change is a pull request against cellucid-python, not against
cellucid. The web-app pages are:
end-user documentation: Web App Guide (
cellucid-python/docs/user_guide/web_app/)developer documentation: Developer Documentation (Web App Architecture) (
cellucid-python/docs/user_guide/web_app/p_developer_docs/)
If you change UI or behaviour in the cellucid repository, update the matching
page here in the same change, so the description users read on ReadTheDocs
matches the app they are running.
When one of those pages points at another page on this site, write the
reference as a {doc} role, never in bare backticks — a backtick is inline
literal text that Sphinx will not resolve, so a wrong target renders as plain
text and survives the -W build. The rule, the relative-path form, and where
backticks are still correct are in
Docs development and style guide.
The reverse also holds: cellucid/CONTRIBUTING.md is read on GitHub, where a
{doc} role is meaningless, so references from that file are written as
repository-relative paths with their .md extension. A path on this page and a
role in that file are not drift; they are the same reference rendered for two
readers.
Build the site before opening the pull request — warnings are errors:
sphinx-build -W --keep-going -b html docs docs/_build/html
The web-app testing, CI, and release checklist is Testing, CI, and release process.
Cross-repository conventions#
These two conventions span every Cellucid repository. Both are enforced, so a change that ignores them fails a check rather than drifting quietly.
Canonical URL forms: www for links, bare apex for identifiers#
cellucid.com is written two ways on purpose. They are not interchangeable and
neither is a typo for the other.
Form |
Use it for |
Why |
|---|---|---|
|
Every navigational URL: documentation links, README links, |
This is the host |
|
Every link into this documentation |
This is the Read the Docs canonical domain: every page declares it in |
|
Every frozen identifier: JSON Schema |
Identifiers must never change once published. A schema |
The identifiers currently frozen at the bare apex are (a new version of a schema gets a new identifier; an earlier one is no longer read):
https://cellucid.com/contracts/community-annotation/user-v3.schema.jsonhttps://cellucid.com/contracts/community-annotation/config-v1.schema.jsonhttps://cellucid.com/contracts/community-annotation/merges-v3.schema.jsonhttps://cellucid.com/ns#(SVG export namespace)https://cellucid.comas the figure-exportgenerator/Websiteprovenance string embedded in every exported PNG and SVG
Rewriting any of those to the www form is a breaking change: it
invalidates already-published schema references and makes figures exported by
two builds disagree about their own origin. Adding a www prefix to them is a
bug, and so is using the bare apex for a link a reader is meant to click.
Separately, https://cellucid.com appears in the Python server’s CORS
documentation as an origin: CORSMixin._get_allowed_origin accepts the
hosted app’s two origins exactly (HOSTED_APP_ORIGINS: the www form and the
apex), so that line is neither a link nor an identifier and stays as written.
Enforcement: cellucid-python/tests/test_canonical_url_contract.py sweeps the
documentation site and the Python sources, requires every navigational URL to
use www, and positively pins each frozen identifier at the apex — so drift in
either direction fails.
CELLUCID_VERSION markers and the cross-repository sweep#
Every hardcoded release version that a version bump must touch carries a
CELLUCID_VERSION marker comment on its line, so grep -rn CELLUCID_VERSION
lists the full edit set. DESCRIPTION in cellucid-r is DCF and cannot carry a
comment, so it declares the convention with a
Config/cellucid/version-marker: CELLUCID_VERSION field instead.
Markers only help inside one checkout. To confirm that all six repositories agree, run the sweep from a workspace that contains them side by side:
python cellucid-python/scripts/sweep_versions.py
It enumerates every version declaration in every repository, groups them by
value with file and line, and separates two things that must not be confused:
declarations that have to agree (the npm name-reservation package in
cellucid/npm/ among them, released under the same version), and artifact
stamps recording which exporter release produced a committed export. It exits
non-zero only on real drift. npm/package.json is JSON and cannot carry a
comment, so its marker is a "cellucid-version-marker": "CELLUCID_VERSION"
field of its config object, on the line after the version.