agentsclimarketplace

Design parity review

Skill yschimke/skills/skills/design-parity-review

Prove a Compose UI pull request matches its intended design by diffing the rendered code (candidate) against a Figma / Stitch / Claude Design reference and posting a parity verdict. Use when asked to check a PR against a design, wire up a design-parity bot, set up the committed reference cache so runs make zero Figma calls, shard an exhaustive catalog check across parallel jobs, map code components to design nodes via design-map.json or Code Connect, or push code renders back onto the Figma canvas. This is the design→code direction; for code→design catalogs see compose-design-catalog and figma-catalog-import.From its SKILL.md

Install
npx -y skills add yschimke/skills --skill design-parity-review

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

10.2 KB, as published. Nobody here has run it

Design parity — reviewing code against its design

design-parity is a tool-neutral bot that proves a UI pull request is at parity with its intended design. On a UI PR it:

  1. resolves which design reference matches the changed component,
  2. renders the new code — the candidate — via compose-preview,
  3. diffs candidate vs reference (visual + semantic + token),
  4. posts a verdict in the PR — e.g. "implements Figma Button/Primary; padding 12dp vs spec 16dp; dark-theme contrast fails AA."

The candidate side is the upstream compose-preview renderer (the compose-preview skill). What design-parity owns is the reference side and the correspondence layer that decides which design maps to which code.

Source

Maintained at github.com/yschimke/skills under skills/design-parity-review/. The tool ships from yschimke/design-parity and on npm as design-parity — run it with npx design-parity …, no checkout needed. That repo's docs/README.md indexes the full contracts; when it disagrees with this skill, it wins.

Which direction is this?

The two directions are different tools and it is worth being explicit, because picking the wrong one wastes a lot of setup:

You wantDirectionSkill
"Does this PR's code match the Figma design?"design → codethis skill
"Publish our component system into Figma as a sticker sheet"code → designcompose-design-catalog → figma-catalog-import
"Is the rendered UI different from last commit?"neither — no design involvedcompose-preview-review

Round-tripping — running both directions on one project — is supported and covered in references/round-trip.md. Read the direction policy section below first: which side is canonical is a committed decision, not a per-run choice.

Set-up order

Do these in order. Each step is useless without the one before it.

1. Decide the direction (.design-parity.json)

Parity has a committed direction. It decides who wins when the two sides disagree, and therefore whether a failing check blocks the PR.

{
  "$schema": "https://github.com/yschimke/design-parity/raw/main/packages/policy/schema/parity-config.schema.json",
  "direction": "code-led"
}
  • design-led — the design is canonical. A parity failure blocks. Right for a team with a maintained design system.
  • code-led — the code is canonical; the design is a reference that may lag. Findings are reported but don't block. Also the precondition for pushing code renders back onto the canvas.
  • auto — resolved deterministically by @design-parity/policy from the repo's maturity.

2. Map code to design (design-map.json)

Correspondence is resolved in this order: Code Connect (Figma only) → committed design-map.json → name convention with a low-confidence flag. Anything but the first two is a guess; prefer to commit the map.

{
  "components": [
    { "code": "ui/Button.kt#PrimaryButton", "source": "figma",
      "ref": "figma:AbCdEf123456/1:42" },
    { "code": "ui/Card.kt#OfferCard", "source": "claude-design",
      "ref": "design/reference/offer-card.html" },
    { "code": "ui/Device.kt#DeviceScreen", "source": "figma",
      "ref": [
        { "ref": "figma:AbCdEf123456/10:2", "state": "default" },
        { "ref": "figma:AbCdEf123456/10:8", "state": "error" },
        { "ref": "figma:AbCdEf123456/10:9", "theme": "dark" }
      ] }
  ]
}

One code handle can bind to several design nodes keyed by state / theme. npx design-parity reverse figma:AbCdEf/1:42 answers the opposite question — which code implements this design node — for sources without Code Connect.

If a repo has no committed design-map.json, the action posts a one-time notice pointing at the interactive bootstrap (design-parity-bootstrap) rather than guessing the mapping at run time, and never blocks. Don't hand-author a map for a project that hasn't run bootstrap — bootstrap also materialises tokens and tuned check thresholds.

A Compose catalog is the exception, and doesn't need bootstrap for the map. If its components already carry @CatalogComponent(reference = …), the map is a projection of those annotations — derive it rather than authoring or bootstrapping it, and the multi-node bindings above come out of the same projection instead of being typed by hand. See Deriving the map from annotations.

3. Pick a reference source

SourceAuthNotes
claude-designnoneCommit the HTML export per screen; rasterized headlessly. Fully offline and deterministic — best fit for a first adoption.
figmaFIGMA_TOKENREST + Code Connect. The only source with automatic correspondence. Rate-limited — see the cache below.
stitchyesstitch:<projectId>/<screenId> (two parts; a single-part ref is rejected). Needs the SDK and a headless Chrome.
bundlenoneA committed directory or .zip of reference PNGs + manifest.json. No design-tool API at all.

4. Render candidates

Parity asserts candidate render ≈ what ships, so render on a target that represents the shipped UI. For Compose Multiplatform, the Desktop/JVM target renders with no Android emulator — the cheapest path, and the reason CMP is the recommended way to try the tool.

Two traps specific to this step:

  • Theme. CMP apps usually theme via MaterialTheme / a CompositionLocal, so the Android night-mode uiMode is unset and the candidate gets no theme — which then fails to pair with a theme-tagged reference. Theme is derived in precedence order: an explicit theme hint on the preview (set this when theming via a CompositionLocal), then the Android uiMode, then the preview id's trailing _Dark/_Light/ Night token (only the last token, so Home_LightOn is not mistaken for light).
  • Semantics. Make sure the bundle carries the semantics blob (a11y tree
    • resolved fg/bg colours + typography). With it, the full a11y/i18n + contrast + token checks run; without it they degrade silently to visual/structural-only.

Platform-specific UI (Android-only APIs, actual impls, Android resources) won't match a Desktop render. Render those on Android, or lift the screen's composable into commonMain.

5. Wire the reference cache — before you wire the run

Do this before the parity workflow, not after. Skipping it is the single most damaging mistake in a real adoption.

A run that fetches every reference live pays the full reference cost on every commit, against a per-token rate limiter. Observed on a 77-component catalog: 18 components produced a verdict and 59 reported figma: rate limited (429) — and a run covering a quarter of the catalog looked exactly like one covering all of it, with a different quarter each run.

The fix is to split the two sides by cadence. See references/reference-cache.md.

6. Wire the parity run

.github/workflows/design-parity.yml, calling the reusable workflow — see references/ci.md for the sharded/exhaustive setup and the standalone action form.

Reading a verdict

Findings are ordered by what actually matters, not by pixel count: a11y + i18n first, then tokens, then pixels. A 3px shift with passing contrast is a lower-priority finding than a dark-theme contrast failure that diffs to almost nothing.

On a push to the development branch the action publishes browsable artifacts to a permanent design-parity/<dev-branch> branch: a landing index.html, each component's self-contained report.html triptych (reference | candidate | diff), a machine-readable verdict.json, and — when the run exposes design-system tokens — the aggregated DTCG table at tokens/design-system.tokens.json.

History accrues automatically: each run re-parents on the branch tip (a linear chain, fast-forward push, no force), and because report.html is deterministic a run that doesn't change a screen touches no file and adds no commit noise. The history therefore shows exactly the runs where a screen's code or mock actually moved.

Reference docs

PathWhen to read
references/reference-cache.mdImporting the design side on its own schedule into a committed cache so the parity run makes zero Figma calls. Why the coupled version silently reported on a quarter of a catalog.
references/ci.mdThe two reusable workflows (import + run), scoping the render, and sharding an exhaustive check across N jobs.
references/round-trip.mdRunning both directions on one project: catalog export out to Figma, parity checks back in, and the opt-in Code-to-Canvas push-back. What must agree between them.

Related

Keep looking

Skills are one crate of 628,971. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.