# Consuming whynot-design from another repo whynot-design is the **upstream visual reference** for other repos. It is a development reference and demo platform — it does not run as a production workload and handles no critical data. Consuming repos build their production UIs *from* it, and follow up on changes **at their own pace** — they are never force-synced. A consumer tracks the **IR** (`ir/`), not the Lit internals. The IR is the technology-neutral contract: per-component contracts (`ir/components/*.json`), W3C-DTCG tokens (`ir/tokens.json`), exemplars, and the version anchor `ir/manifest.json`. Three moves make this work: 1. **Pin** a version — the package + your lockfile. 2. **Inspect** it — `ir/INDEX.md` (browsable) + `ir/manifest.json` (machine). 3. **Get a grip on changes** — `npx @whynot/design drift`. This is the inverse of whynot-design's own upstream machinery (`Claude Design → designbook/ → ir/`), now pointed downstream (`ir/ → your repo`). It is **one-way**: you read the IR; you never write back. --- ## 1. Pin a version `@whynot/design` is published to the coulomb Gitea npm registry. Pin an exact tagged version; your lockfile becomes the real pin. ```bash # .npmrc in your repo (see PUBLISHING.md for the read-token routing) # @whynot:registry=https://gitea.coulomb.social/api/packages/coulomb/npm/ npm i @whynot/design@0.3.0 lit ``` `lit` is a **peer dependency** — install it alongside so your bundler dedupes to a single `lit` instance. ## 2. Inspect what you pinned No clone, no build needed: - **`node_modules/@whynot/design/ir/INDEX.md`** — human-readable catalog: every component, its tag, props/variants/slots/events, and a link to its exemplar. - **`node_modules/@whynot/design/ir/manifest.json`** — the machine inventory: `designVersion`, a `tokensHash`, and a content `hash` per component. ## 3. Adopt a sync-point Record which IR state your repo has reconciled against. Run once, in your repo root: ```bash npx @whynot/design drift --update ``` This writes **`.whynot-design.lock`** — commit it. It is the consumer-side mirror of whynot-design's own `designbook/.design-sync.json`. ### `.whynot-design.lock` format ```json { "designVersion": "0.3.0", "adoptedAt": "2026-06-27T17:31:08.640Z", "manifestSchemaVersion": "1.0.0", "manifestHashes": { "tokens": "sha256:426f565a9ce6c36f", "components": { "Button": "sha256:4a32713049e433dd", "TopNav": "sha256:32ebc6e46db38f93" } } } ``` | field | meaning | | --- | --- | | `designVersion` | the `@whynot/design` version you adopted | | `adoptedAt` | when you adopted it (first adopt, or last `drift --update`) | | `manifestSchemaVersion` | the manifest's shape version; a mismatch warns that hashes may not be directly comparable | | `manifestHashes.tokens` | adopted value of the manifest `tokensHash` | | `manifestHashes.components` | adopted content hash per component | **Lifecycle:** created on first `drift --update`, advanced only by a later `drift --update`. Nothing else writes it. Schema: `ir/schema/lock.schema.json`. ## 4. Follow up at your own pace When you bump `@whynot/design` (or just want to know what moved), run: ```bash npx @whynot/design drift ``` It compares your adopted `.whynot-design.lock` against the installed package's `ir/manifest.json` and reports **added / changed / removed** components plus whether **tokens** changed: ``` whynot-design drift adopted: 0.3.0 (2026-06-27T17:31:08.640Z) target: 0.4.0 (2026-07-10T09:02:11.400Z) Tokens: changed Components: +1 added · ~1 changed · -0 removed · 11 total + Banner ~ Button Drift detected vs your adopted sync-point. Adopt this version: npx @whynot/design drift --update ``` Then, when *you* are ready, review the changed contracts in `ir/INDEX.md`, update your UI, and adopt the new sync-point: ```bash npx @whynot/design drift --update ``` ### Exit codes (CI-friendly) Mirrors the adapter contract (`adapters/ADAPTER_CONTRACT.md`): | code | meaning | | --- | --- | | `0` | in sync — your lock matches the target | | `2` | usage / config error (bad flag, missing/invalid manifest or lock) | | `3` | **drift detected** — something changed since your sync-point | Add `--json` for automation. Useful flags: `--manifest ` (diff against an explicit manifest, e.g. a fetched newer version on disk), `--version ` (assert the resolved manifest is that version — guards against the wrong install), `--lock ` (non-default lock location). > **No network, no writes to the package.** `drift` reads only the > already-installed package + your lock, and the only file it ever writes is your > repo's `.whynot-design.lock`. --- ## Try the full loop now A copy-pasteable fixture lives at [`examples/consumer-fixture/`](./examples/consumer-fixture/) — it exercises pin → inspect → drift → update against a fixed version without needing a real install. See its `README.md`. See also: [`README.md`](./README.md) *Tracking whynot-design* · [`MultiFrameworkSupport.md`](./MultiFrameworkSupport.md) · [`ir/SCHEMA.md`](./ir/SCHEMA.md).