Guides

Contributing

motif is a Yarn-workspaces monorepo built with Turborepo. To contribute, clone it, install once, and run the four gates — build, test, typecheck, lint — that every change has to pass before it merges.

Updated 3 days agoEdit on GitHubWeb & native

Set up the repo

motif needs Node 20 or newer and Yarn 4. The repository pins its Yarn version through Corepack, so you do not install Yarn yourself — enable Corepack and it uses the pinned release.

example.tsx
corepack enable
git clone https://github.com/foo-stack/usemotif.git
cd usemotif
yarn install

yarn install wires every workspace together. Packages depend on each other through workspace:* ranges, so a change in @usemotif/core is visible to @usemotif/react with no publish step and no rebuild of node_modules.

How the monorepo is laid out

The tree splits by role. Most contributions touch packages/.

DirectoryWhat lives there
packages/The 14 published packages — core, react, react-native, headless, the four compiler-*, tokens, icons, reset, test-utils, migrate, and the usemotif meta package
apps/The documentation site and the SSR example apps
examples/Runnable sample projects
e2e/End-to-end browser tests
benchmarks/The performance suite run on every release
tooling/Shared build and config packages

packages/core holds the renderer-agnostic resolver — tokens, the style schema, the responsive system. packages/react and packages/react-native are thin renderer bindings over it. A behaviour change usually starts in core; a platform-specific change stays in one binding.

The four gates

Every change has to pass the same four commands CI runs. Turborepo caches results, so a second run only rebuilds what changed.

example.tsx
yarn build       # turbo run build      — every package compiles
yarn typecheck   # turbo run typecheck  — no type errors
yarn test        # turbo run test       — unit + conformance suites
yarn lint        # oxlint               — no lint errors
yarn format      # oxfmt                — apply formatting

Run yarn format before committing — it rewrites files in place — and yarn lint to catch what formatting does not. The lint gate fails on errors only; warnings are advisory.

The conformance bar

A change to how a prop resolves is not finished until both renderers still agree. The @usemotif/test-utils conformance suite is the contract: standardCases describes a resolved style for a given primitive and props, and each renderer runs every case through its adapter.

If your change alters resolution on purpose, update the affected standardCases entries in the same pull request — the case list is the spec, so the diff to it is the clearest statement of what behaviour changed. If a case fails and you did not mean to change resolution, that is the suite doing its job. See Testing for how the suite is wired.

Open a pull request

Keep a pull request to one concern. A bug fix, a single feature, one package's refactor — each is its own branch and its own review. A core change plus the react change that consumes it can travel together, since the conformance suite needs both to stay green; an unrelated cleanup should not ride along.

In the description, say what changed and why, and link the issue if there is one. Note any change to a standardCases entry explicitly — a reviewer reads the case diff first to see what resolved behaviour moved.