whynot-design/CONSUMING.md
tegwick 6de4d31bde
All checks were successful
CI Smoke / host-smoke (push) Successful in 1s
CI Smoke / container-smoke (push) Successful in 20s
Migrate npm and git refs to Forgejo (RAIL-HO-WP-0006)
2026-07-09 11:59:08 +02:00

5 KiB

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 changesnpx @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.

# .npmrc in your repo (see PUBLISHING.md for the read-token routing)
# @whynot:registry=https://forgejo.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:

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

{
  "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:

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:

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 <path> (diff against an explicit manifest, e.g. a fetched newer version on disk), --version <x.y.z> (assert the resolved manifest is that version — guards against the wrong install), --lock <path> (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/ — it exercises pin → inspect → drift → update against a fixed version without needing a real install. See its README.md.

See also: README.md Tracking whynot-design · MultiFrameworkSupport.md · ir/SCHEMA.md.