Skip to content

Specifications

A component spec records what a component must be: its parts, its props, the tokens it uses, and the behavior a picture can’t show. Decide which tool holds that record before anyone builds, and write it precisely enough that a team who never met the designer can build from it.

A spec used to be a note from a designer to the developer sitting next to them. That stops working once a system ships to several codebases. Nathan Curtis notes that “a three platform setup (iOS, Android, and web) is common, and some systems like IBM Carbon spread across many more.” One design decision now has to reach teams who never sit in the same standup.

Each of those teams fills the gaps in a design file differently. One guesses a spacing value, another invents a prop name. Nobody decides that the disabled button looks different on iOS than on Android. It just does, and nobody notices until a user switches platforms.

Code generation makes the gaps more costly. Before Curtis’s spec tool recorded each part’s role, it turned three look-alike pills (a plain one, a checkbox, and a toggle button) into the same div with ARIA attributes (the HTML attributes screen readers announce) added on top, because nothing in the file told them apart. Accessibility tells the full story. A developer reading the file might have asked which pill was which. The generator didn’t.

Figma, the code, and the docs site each hold part of a component’s truth, and they routinely disagree. Shane P Williams says “none of the three is lying. They are each authoritative for a different question”: Figma for what was intended, Storybook for what was built and documented, production for what shipped. A spec answers the first question, and it has to be finished before build. The design contract is met only when “the spec can be built without clarifying questions.” So the test is which tool lets your team write the full intent early, and generate the other outputs from it. Someone still has to keep the layers in agreement afterward. AI Governance covers that role.

Designers keep working where they already work, and a tool turns the file into data. Curtis’s specs-cli reads a Figma library and writes one compact spec per component into the repo, with anatomy, props, styles, token Citations, and variants. Coding agents then read those files, not Figma (Figma Agent Access). This fits design-led teams with a large library already built carefully in Figma.

The cost is that Figma has no field for much of a spec, so it gets squeezed into whatever Figma does have. Roles go into Dev Mode annotations. Code-only props go into nested instances on a layer named “Code only props”. Code keys come from layer names, which lose separators, casing, and punctuation on the way (Property Naming). Even Curtis’s own team doesn’t stop at Figma. His designers mark a component READY_FOR_DEV, then “conduct an agentic pass to compose the behaviors and accessibility Figma can’t.”

The spec is a YAML or JSON file next to the code. Figma, each platform’s code, and the docs pages are all generated from it. This is the direction of Curtis’s “Components as Data”, where Figma becomes one output of the data alongside generated code. Murphy Trueman’s toolkit keeps a similar metadata file per component, including the prop combinations the system blocks, which Trueman calls prohibited combinations (API Design).

flowchart TD
    D[Spec data in the repo] --> F[Figma]
    D --> C[Code for each platform]
    D --> S[Docs site]

A docs site built with Astro or Storybook can then render the spec rather than restate it. Romina Kavcic applies the same rule to tokens: people browse and discuss them in a synced view but never edit values there. “Stop manually copying token values from your repo to documentation.” Diana Wolosin’s team at Indeed authors component docs in MDX and converts them to JSON for agents (Agent CI Pipelines). That’s the docs-first version of the same idea. No source here yet describes a full spec, roles and anatomy included, written directly in a docs site, so treat that variant as an open question.

This fits multi-platform systems where no single tool should own the definition. The cost is building the scripts that generate each output. Designers also need a way to edit the spec without opening a YAML file.

Storybook 10.3 generates a Component Manifest that lists components, props, stories, and docs, and an MCP (Model Context Protocol, the standard way agents read data from other tools) add-on lets agents query it (Trueman). It costs almost nothing to set up, and it always matches what was built. It fits a code-first team with no separate design source, or works as a check against the other two options.

The cost is that it describes what exists, not what was intended. It can’t be the spec for a component nobody has built yet. It also leaves out composition, tokens, and status until someone adds them (AI readiness).

Curtis argues that spec quality has to rise as a system grows past one platform. A spec is no longer a note for one team. It has to state intent precisely enough that teams who never talk to each other still build the same thing. In practice, that means the anatomy (named parts and how they nest), every prop with its type, options, and default, every state, and the tokens each part uses. Designers and developers should agree on the anatomy and props together before build, as Property Naming describes. The EightShapes Specs plugin exists because listing all of this by hand stops scaling once a spec serves three or more teams.

Some facts aren’t visible in any design file, so readers and tools fill them in by guessing. Whichever option you chose above, give these facts a field in the spec.

The first is each part’s role and action. “The role is an authored fact that must be carried in the spec,” Curtis concludes, and he keeps what a part is separate from what activating it does (Accessibility). The second is which prop combinations the system supports. Supernova warns that “if your system permits a certain usage, it will likely be used that way somewhere in the product” (API Design). The third is code-only props like id and ariaLabel, which change nothing on screen (Property Naming).

A token reference carries meaning that a value doesn’t. Curtis’s example in “Components as Data” is a raw color in a variant where a token was required. You can’t see that error in a rendered mockup, but it’s obvious in the data. The same loss shows up when a spec goes back into Figma. First on Curtis’s list of what specs leave behind is “emitting a hex code when a color token is bound.” The component looks right today and misses the next rebrand. Rendering the spec back is how you find these losses. Figma Agent Access covers that round trip.

Structured data only pays off if something checks it against a schema: a machine-readable list of the fields a spec may have and the values each one allows. Curtis draws the line in “Component Contracts and Schemas”: “a description informs. A contract arbitrates.” His smallest example is a single prop:

Contract excerpt
props:
size:
type: string
enum:
- small
- medium
- large
default: medium

The enum (a fixed list of allowed values) “reduces any possible size to three legal choices.” In a loose document, “every value is just text, and text accepts anything,” so size: med slips through. Against the schema, it fails.

Write the spec once, neutrally, and let each platform build its own native version from it. Specs maintained by hand for each platform drift apart the same way parallel implementations do. Platforms will still differ. Values that differ, like San Francisco on iOS and Roboto on Android, belong in tokens. Structure that differs, like a confirmation that’s a dialog on iOS and a bottom sheet on Android, belongs in the spec as a recorded decision. Platform divergence owns that split.

  • Calling the Storybook page the spec. In Williams’s split, Storybook answers what was built, not what was intended. If the build drifted from the intent, the drift now looks like the intent, and nothing is left to check it against.
  • Hoping layer names will carry behavior. In Curtis’s test library, no layer structure or naming pattern told a checkbox pill from a toggle button. A naming convention can’t hold a role.
  • Assuming Figma annotations reach code. A role annotated in Dev Mode only reaches code if code is generated from the spec, as Curtis’s tool does. A developer building by hand may never open the annotation.
  • Expecting a lossless round trip. Curtis found intent that specs can’t carry yet, like the order of props in Figma’s panel. His advice is to keep rendering until you know “what you are missing, and how much you value it.”
  • Confusing multi-platform with cross-platform. The goal isn’t one implementation forced to look the same everywhere. It’s one set of decisions, expressed natively on each platform.