Contributing
When you finish this page you know which parts of Sorb™ you can clone and change, how the open-source packages fit together, and how to get a fix merged. You need Node 20 and pnpm.
What's open source
Sorb™ is split across several repositories. The packages you install and the demos you can copy are public on GitHub; the hosted service and Metatoy's internal tooling are not.
| Public repo | What it is | npm |
|---|---|---|
sorb-core | Shared contract: tiers, ResolvedToken, connector registry | @sorb/core |
sorb-seed | Playwright capture + token resolver, adapt codemods, sorb-seed CLI | @sorb/seed |
sorb-leaf | React SDK: SorbProvider, PreviewBanner, hooks, target adapters | @sorb/leaf |
sorb-juice | Local bridge server + sorb CLI (sorb dev, sorb handshake, …) | @sorb/juice |
sorb-canopy | The Figma plugin | — (source + zip release; not on the Figma Community yet — see Install (beta)) |
sorb-storybook | Storybook addon: Bound Tokens panel | @sorb/storybook |
sorb-tap | Read-only MCP server for design tokens (a DTCG file, a Sorb project, or a running bridge) | source only |
sorb-demo | Jane's Jeans reference app (React + Bootstrap) | — |
sorb-demo-kit | The Jane's Jeans brand kit: DTCG token tree, fixtures, imagery, component inventory | — |
sorb-demo-{angular,mantine,mui,primevue,tailwind} | The multi-stack demo storefronts built from the kit | — |
Private, not open to outside contributions: sorb-cloud (the hosted
service behind app.sorbcloud.com), this documentation site, Metatoy's
end-to-end test suite, the try.sorbcloud.com tour, and the internal test
fixtures. You can't clone them, and pull requests aren't accepted there. If
something in the hosted product is wrong, use Support — it reaches
the same people.
Workspace layout
The public repos are a polyrepo: each lives in its own git repository, and
the packages that develop against each other's checkout sit side by side under
one umbrella directory with a pnpm-workspace.yaml at its root. A minimal
contributor checkout looks like this:
mkdir sorb && cd sorb
git clone https://github.com/metatoy/sorb-core
git clone https://github.com/metatoy/sorb-seed
git clone https://github.com/metatoy/sorb-leaf
git clone https://github.com/metatoy/sorb-juice
git clone https://github.com/metatoy/sorb-demo
printf "packages:\n - 'sorb-*'\n" > pnpm-workspace.yaml
pnpm install
With the workspace file in place, sorb-demo resolves @sorb/leaf and
@sorb/juice from the sibling checkouts instead of npm, the same way
sorb-seed, sorb-leaf, and sorb-juice resolve @sorb/core. Repos that
are not workspace members — the plugin, the Storybook addon, and each
multi-stack demo — install and run on their own; their READMEs say how.
JavaScript only
Every public repo is JavaScript, not TypeScript — types are JSDoc typedefs in
a src/types.js file, and builds use esbuild rather than a TypeScript
compiler. A pull request that adds a .ts file or a typescript dependency
to one of them will be asked to change.
Two more rules that apply everywhere: don't commit generated output (dist/,
.sorb/, src/tokens/generated/), and don't add a per-package lockfile to a
pnpm workspace member — the umbrella pnpm-lock.yaml is the only one.
Package manager per repo
| Repo | Package manager |
|---|---|
sorb-core, sorb-seed, sorb-leaf, sorb-juice, sorb-demo | pnpm, as workspace members (pnpm install from the umbrella root) |
sorb-canopy, sorb-storybook, the multi-stack demo repos | npm, each with its own lockfile |
Send a change
- Fork the repo you're changing and branch from
main. - Run that repo's tests before and after —
node --test src/insorb-core,pnpm testinsorb-seed,npm testinsorb-leafandsorb-juice. Other repos name their command in their README. - Keep the public surface documented: if you add or change an export of
@sorb/core,@sorb/seed,@sorb/leaf, or@sorb/juice, give it a JSDoc block — the package reference on this site is generated from those comments, and an undocumented export fails the docs build. - Open a pull request with what changed and how you verified it. A maintainer reviews it; releases to npm are cut by Metatoy from a version tag with provenance, so you don't need to bump versions.
Bug reports and feature requests go in the issue tracker of the repo they belong to. For anything about the hosted product (accounts, billing, the dashboard), use Support instead — that code isn't public.
Maintainers: this documentation site
This section is for Metatoy maintainers. The docs site's repository is private.
The deployable app lives under www/, not the repo root:
cd sorb-www/www
npm install
npm run dev # http://localhost:3000/docs
Docs pages are MDX files under app/docs/<route>/page.mdx. Follow the shape
of an existing page — pageMetadata() for the frontmatter-equivalent, an
<h1> naming the reader's task, a <p className="lead-line"> stating the
outcome and prerequisites, then sections, then a ## Next list of links.
Screenshots are never invented: use the Shot placeholder component
(app/docs/Shot.jsx) until a real capture exists.
Regenerate the API reference
The package reference pages (/docs/packages/core|seed|leaf|juice) are built
from generated partials, not hand-written prose. The generator reads sibling
checkouts in the umbrella workspace — it needs sorb-core, sorb-seed,
sorb-leaf, and sorb-juice checked out next to sorb-www (or pointed at
via SORB_WORKSPACE, default ../.. from www/; SORB_REPO_<PKG> overrides
a single repo path):
npm run gen:api # regenerate app/docs/packages/_generated/*
npm run check:api # fail if the committed output is stale, or any export
# is undocumented
Run npm run gen:api after any change to @sorb/core, @sorb/seed,
@sorb/leaf, or @sorb/juice's public surface, and commit the regenerated
files under app/docs/packages/_generated/ — they are committed output, not
build artifacts, because the production Docker build only sees www/ and has
no sibling checkouts to generate from.
Checks
Three of these run automatically, in order, as npm run build's prebuild
step (check:no-ts && check:blocklist && check:api); the rest you run by
hand at the point they're each useful:
| Command | What it checks | When |
|---|---|---|
npm run check:no-ts | no .ts/.tsx files or TypeScript deps under www/ | in prebuild |
npm run check:blocklist | no internal hosts, secrets, retired names, or private repos presented as cloneable in app/docs/** | in prebuild |
npm run check:api | the committed API reference matches the sibling source, and nothing is undocumented | in prebuild |
npm run check:mdx | every app/docs/**/*.mdx file compiles (fast — no full next build) | run it yourself while editing MDX, before committing |
npm run check:links | every internal link in the built site resolves | after npm run build — it crawls the built .next/ output |
npm run check:snippets | the copy-paste commands in Getting started actually run, end to end | before merging a change to the getting-started snippets |
Next
- Getting started — the reader-facing quickstart these docs teach.
- Package reference — the generated surface of the four npm packages.
- Demos — the storefronts you can fork to try a change end to end.
Works with Figma. Not affiliated with, or endorsed by, Figma. Figma is a trademark of Figma, Inc.