Skip to content

04 · Craft: 12 brand-agnostic rules ​

A design system decides what it looks like. Craft decides what counts as acceptable.

Those are two different things, and OpenDesign separating them is right: changing brands shouldn't move the accessibility floor, and choosing a striking visual style shouldn't cost the button its disabled state.

How it works ​

A skill declares which craft rules it needs in its frontmatter. Loading the skill loads those rule files into the system prompt.

Quality constraints therefore travel with capability, and you don't restate them per prompt. You write "a landing page" and accessibility, state coverage, and typographic hierarchy come along.

The twelve ​

#NameWhat it governs
01Accessibility baselineThe legal floor, plus the craft commitments beyond it
02Animation disciplineWhether motion earns its place, and the numbers that bound it
03Anti-AI-slop rulesConcrete rules separating "shipped by a human" from "default LLM output"
04ColorHow to use the palette the design system supplies
05Editorial typography hierarchyHierarchy for long-form articles, magazine layouts, editorial pages
06Form validationValidation lifecycle, error wiring for assistive tech, where the rule lives
07Future Craft SectionsA register of slugs skills already reference before the rule files ship
08Laws of UXResearch-grounded cognitive and behavioural heuristics that decide composition
09RTL and bidirectionalRight-to-left layout, and mixed direction within a line
10State coverageWhich states every interactive surface must render
11TypographyUniversal type rules on top of any design system
12Typography hierarchyHow hierarchy is established, broken, and when breaking is allowed

Number 07 isn't a rule

"Future Craft Sections" is a register: skills already declare dependencies on rules whose files don't exist yet. pnpm lint:craft treats those as planned forward references while still failing on unregistered typos. It's in the catalog so the arrangement stays visible rather than implicit.

The three that bite most often ​

State coverage ​

The official phrasing is worth keeping: the single most reliable AI-design failure is shipping only the populated state.

Generate a list view and you get a handsome list full of data. What about empty? Loading? Errored? One item? A thousand?

This rule requires the states to be written. Use it as your acceptance list too:

  • [ ] Empty (with a way forward)
  • [ ] Loading
  • [ ] Error (saying how to recover)
  • [ ] Minimal data (one item)
  • [ ] Heavy data (pagination or virtualisation?)
  • [ ] Unauthorised

Anti-AI-slop ​

This one is unusual: some of its rules are auto-enforced by the daemon's lint-artifact linter. Failing an enforced rule is a regression, not a style preference.

The rest are guidance for agents and reviewers, and the file marks them inline as "(guidance, not auto-checked)". Stating the boundary out loud is more useful than claiming everything is checked — you know what to rely on and what to inspect.

See 05 · Anti-slop.

Animation discipline ​

The design system decides motion's personality; this rule decides whether motion runs at all, plus duration, easing, and the accessibility floor.

The floor is the part most often forgotten: prefers-reduced-motion must be honoured. If a user has turned motion off at the OS level, your page doesn't move. That isn't a preference.

Declaring craft in your skills ​

In SKILL.md frontmatter:

markdown
---
name: your-skill
craft: [accessibility-baseline, state-coverage, typography-hierarchy, color]
---

Which ones depends on what the skill produces:

ProducingDeclare
Interactive interfacesaccessibility-baseline, state-coverage, form-validation, laws-of-ux
Landing pagesaccessibility-baseline, typography-hierarchy, color, animation-discipline
Long-form / editorialtypography, typography-hierarchy-editorial, color
Deckstypography-hierarchy, color, animation-discipline
Anything internationaladd rtl-and-bidi

Invoking it by hand ​

Without a skill, reference it in the prompt:

text
Bring this version up to state coverage: empty, loading, error, single
item, and heavy data — each with its own rendering. Don't ship only the
populated state.

Then self-check against the anti-AI-slop rules, list what you hit, and
fix it.

Useful at acceptance time. Running it after generation surfaces a set of problems you've already stopped seeing.

An unofficial community guide · compiled from open-design.ai public material and hands-on notes · the official docs win where they differ