design-sync notes — myMat Brand Kit

Project: myMat Brand Kit — https://claude.ai/design/p/8e7513e1-b429-4b24-a72d-59f318ac7d54 First synced 2026-08-28. Shape: package, tokens-only (no components).

What this repo is

An Eleventy static site, not a React component library: no dist/, no Storybook, no .jsx/.tsx anywhere. The converter's documented tokens-only path handles this — it prints [ZERO_MATCH] no component exports — treating as tokens-only DS and emits styles.css + tokens/ + fonts/ with an empty-bodied _ds_bundle.js. That line is expected, not a failure.

The uploaded kit is therefore CSS only. window.MyMatBrand is empty by design; .design-sync/conventions.md tells the design agent so explicitly, because the generated README body otherwise claims it is a React library.

The brand-pkg generation step

cfg.cssEntry is bounded by design-sync to the package directory (its content uploads verbatim), so it cannot point at assets/css/site.css. Instead .design-sync/build-brand-pkg.mjs regenerates .design-sync/brand-pkg/ from the site's own CSS. It is cfg.buildCmd — run it before every re-sync.

Inputs and how they are split (logic in brand-kit.mjs, tested in test/brand-kit-css.test.mjs):

As of 2026-08-28 all 44 shared rules were byte-identical, so nothing is lost to de-duplication. site.css's own header comment warns that the four original pages still carry inline copies — if those pages are ever pointed at site.css, or the copies drift, re-check that assumption.

Two behaviours are load-bearing and fail silently, which is why they are unit-tested rather than eyeballed:

  1. @font-face url rewriting. The site declares fonts absolutely (url('/assets/fonts/…')). design-sync resolves url()s against the stylesheet dir and an absolute path wins, so unrewritten rules never copy the .woff2 and every design silently renders in a fallback font. The generator rewrites them to ../../assets/fonts/… and they are wired via cfg.extraFonts (bounded to the workspace root, unlike cssEntry).
  2. De-duplication keys on selector + normalised body, not selector alone — both sources declare @media (max-width: 820px) with different bodies.

Fresh-clone setup

.design-sync/brand-pkg/ is gitignored (generated). Recreate it and the symlink that cfg.tokensPkg resolves through:

node .design-sync/build-brand-pkg.mjs
ln -sfn ../../.design-sync/brand-pkg .ds-sync/node_modules/mymat-brand

Re-sync

# re-copy the staged scripts first (a stale .ds-sync/ runs an old converter)
node .design-sync/build-brand-pkg.mjs
node .ds-sync/resync.mjs --config .design-sync/config.json \
  --node-modules .ds-sync/node_modules \
  --entry .design-sync/brand-pkg/index.mjs \
  --out ./ds-bundle --no-render-check \
  --remote .design-sync/.cache/remote-sync.json
node .design-sync/validate-conventions.mjs

Then re-read conventions.md against the fresh build — keeping it true is a standing job; do not rewrite it, report drift.

Decisions on the record

Re-sync risks