Files
zeekayandHanzo Dev 1776747704 design: one skill teaches the system, one lint proves the code reached it
An agent had no way to LEARN this design system. prompts/ was material for a
human to paste, so every generated surface re-derived the rules from scratch —
and got them wrong the same ways each time: 117 all-caps labels, 586
inline-styled buttons, 25 z-index literals, a menu painting with tokens nothing
declares.

So: skills/design-system/SKILL.md, one file, one author. It states the
derivation chain (@hanzo/brand + @hanzo/logo -> @hanzo/design -> component) and
the rule that follows from it — a component reads the token layer and never
reaches past it; a missing token is a NEW TOKEN, not a local constant.

Guidance nothing enforces is advice. scripts/lint.mjs is the gate the skill must
run before returning, and it reads CONSUMER code, not just this repo:
unresolved var(), raw colour, magic z-index, px font-size, non-eyebrow caps,
literal-valued inline style, a second icon set, and the wrong package name.
None of those fail loudly on their own. That is exactly why they ship.

Run against this repo it found nine violations in the design system's OWN
components — Dialog and Sheet hardcoded zIndex:80 and rgb(0 0 0 / .8) while
publishing --z-modal to everyone else. Fixed at source, and the two scrims that
disagreed are now one --surface-scrim token. npm test runs both gates.

Also: every doc told agents to import @hanzoai/design. That package does not
exist; the import resolves to nothing and an unresolved token layer paints
nothing. It is @hanzo/design, in all ten places.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-27 18:24:03 -07:00

2.0 KiB

docs — how to use the system

The design system is one idea applied without exception: Hanzo is monochrome, true black, white type, and color is a signal — never a decoration. Everything else is machinery in service of that idea.

If you remember one thing: import one file, then reach for a token instead of a literal. Do that and your surface is already 90% on-brand.

@import "@hanzo/design/styles.css";

The map

You want Go to
To wire the tokens into an app integrate.md
The raw values (color, type, space, radius, motion, z, elevation) ../tokens/
A component and how to use it ../components/ + its *.prompt.md
To see a rule rendered ../guidelines/ specimen cards
An AI to generate an on-brand screen ../prompts/
The words — voice, taglines ../content/
The mark, wordmark, logos ../assets/

Why it is built this way

  • One import. A single styles.css pulls the whole token layer in a fixed order. There is no partial setup to get wrong.
  • Tokens, not literals. Every value is a CSS custom property whose name matches hanzo.ai's own variables. Code copies between the app and this system 1:1, because they speak the same names.
  • Dark by construction. Surfaces mount dark. Light is a .light override for the few brand and docs pages that need it.
  • Opacity is the palette. One neutral ladder plus an opacity ladder is the entire non-semantic color system. Rank reads as opacity. This is why Hanzo looks like Hanzo and not like a theme.
  • The parts are self-contained. Components carry their own inline styles, so one drops into Next, Vite, Tamagui, or nothing and renders identically.

The one rule that overrides the rest

When a decision is unclear, return to the atom. Monochrome, true black, white type. If the work reinforces it, keep the work. If it doesn't, change the work.