#Contributing
#Commands
bun install
bun test # the full suite
bun run typecheck
bun run docs # rebuild this site into site/
bun run playground # rebuild preview/playground.html
bun run preview # rebuild preview/contact-sheet.png
bun run convert-assets # regenerate src/data/*.json from vendor/
bun run sync-backend-snapshot # refresh the backend catalogue snapshot (monorepo only)#Layout
src/
body/ geometry loading, types, and intensity resolution
color/ OKLCH conversion and the intensity scale
core/ the platform-agnostic renderer and its primitives contract
data/ GENERATED body maps - never hand-edit
muscles/ the 49-code catalogue
index.ts pure exports (no React)
native.tsx react-native-svg entry
web.tsx DOM SVG entry
docs/ this documentation, as Markdown
playground/ the interactive playground app
scripts/ converters and site builders
vendor/ upstream artwork, kept for re-conversion#What is generated
Four things, all rebuilt from a source of truth rather than maintained by hand:
| Output | Built from | By |
|---|---|---|
src/data/*.json |
vendor/ artwork |
convert-assets |
site/ |
docs/*.md + the live catalogue |
docs |
preview/playground.html |
playground/ + the real package |
playground |
tests/fixtures/backend-muscle-catalogue.json |
core-service constants | sync-backend-snapshot |
The documentation tables for the catalogue, coverage matrix and intensity ramp are generated from the actual exports at build time. A hand-written table drifts; a generated one cannot.
#Invariants the tests protect
These are the things that would break quietly, so they each have a test:
- Backend parity. All 49 codes, names and statuses match the backend catalogue. Inside the monorepo this checks the live Python file and that the committed snapshot still agrees with it; standalone, it checks the snapshot alone and skips the comparison.
- One-hop aliases. No alias points at another alias. Every code resolves to a drawn region.
- Every extended code states a reason.
aliasOfandaliasNoteare both required. - The resolution breakdown. 23 drawn, 18 splittable, 5 deep, 3 side-view - so the documented counts cannot go stale.
- Coverage. All 23 drawn regions appear on at least one diagram, and no code is unrenderable across all four.
- The female back omits exactly
ANKandHEA. Keeps the artwork and the backend's"Both (Front only for female)"annotation in agreement. - Merge semantics. Collisions take the maximum, and order does not matter.
- Colour. Anchors return exactly; out-of-range clamps; OKLCH beats sRGB blending on chroma at the midpoint.
- The playground actually runs. The built HTML is loaded into a DOM and executed. It also
asserts the file contains exactly one
</script>- React DOM embeds the literal string"<script></script>", and an unescaped copy closes the tag early, leaving the browser to render the rest of the bundle as visible text.
#Publishing the docs
bun run docs writes a fully static site to site/ - plain HTML with relative links, so you can
open site/index.html straight from disk with no server.
The GitHub Actions workflow at .github/workflows/docs.yml builds and deploys the same output to
GitHub Pages on every push to the default branch. Pages needs to be enabled once, under
Settings → Pages → Source: GitHub Actions. On a private repository this requires a paid GitHub
plan; on a public repository it is free.
#Before open-sourcing
- Remove
"private": truefrompackage.json. - Claim the
@gravnnpm scope, or rename the package. - Confirm
NOTICEandLICENSEboth ship - the upstream MIT attribution is a licence obligation, not a courtesy.