Skip to content

Brilliant for design system leads

A design system only holds if the people using it can't easily go around it. In Brilliant the system is a plain-text file in the project, one seed color expands into an 11-step OKLCH ramp, and every agent working on the canvas gets the token catalog in context. Agents paint with roles, not hex.

Nobody has to remember to comply. The tokens are the shortest path.

The system is a file in the repo

Each project has a Styles/ folder with default.ds inside it: the file you edit. Brilliant writes a fully populated version when you open a fresh project, so there's something real to start from on day one.

my-project/
├── Styles/
│   ├── default.ds               ← you edit this
│   └── .gen/
│       └── default.gen.yaml     ← auto-generated, don't edit
└── Canvas.bl

default.gen.yaml is the resolved output, regenerated on every save with everything expanded to concrete values. That's the file external tooling reads: Style Dictionary, Tokens Studio plugins, build scripts.

Primitives, semantics, and five generators

The central model: primitives are 1:1 (one fixed value), semantics are 1:N (one value per mode). Primitives give you raw stops like primary.50..950. Semantics give you mode-aware roles like primary.mid and spacing.md, which resolve differently in light versus dark, comfortable versus compact.

A primitive token rendered identically on light and dark panels, next to a semantic token resolving to a different value in each mode

Five built-in generators do the expansion: color() and number() produce primitives, and boldness(), tshirt(), and looseness() wrap a primitive scale into mode-aware roles. Three vocabularies cover every domain: boldness for tones and weights, t-shirt for spacing, radius, and font size, looseness for line height and letter spacing.

Agents are held to it

When a design system is active, every color, size, and font slot an agent writes is a $token resolved through the current brand and mode rather than a bare value:

al(v,g($spacing.md),pad($spacing.lg)) s(280,hug) f[($color.surface)] rd($radius.lg) "Card"
  t("Real-time sync",$font.family,$font.size.lg,b) f[($color.text.primary)]

The agent has your catalog in context, so it reaches for color.surface and spacing.md on its own. Ask it to bind a stray fill to the closest token and it will.

Because every slot is a role, the whole design answers to one switch. This card is on an alternate brand; change the brand, flip the theme, or tighten the density, and everything the agent painted moves with the system:

Brand
Theme
Density
Live on a desktop browser with WebGPU. One scene, one design system: switch brand, theme or density and every value the system drives moves at once.

Modes and brands, without a second file tree

Modes are named axes. The seed template ships three (theme, density, accessibility) and you can declare any others you want. A brand is a sparse sibling .ds file that declares only its deltas: a seed, maybe a font family, a few overrides. Everything else cascades from the base, and the cascade walks the folder tree like .editorconfig, including root: true to stop it.

Where the edges are

Brilliant has no published component library and no library export: masters are regular frames you keep on a canvas by convention, and there's no component description or metadata layer. Primitives are mode-independent by design, so a value that must differ per mode needs a semantic in front of it. And a raw hex on an element stays a raw hex: it won't re-skin when you switch, which is the one failure mode worth auditing for.

Next