Skip to content

One UI language. Everywhere.

Your product already has a design system. Or it will. The usual mistake is tying that system to one framework.

React this year. Angular in another product. Vue in a marketing site. AI generating screens next quarter. The brand should not rewrite itself each time.

One UI language. Everywhere.

That is the customer promise. Airframe is not that design system. Airframe is the grammar it sits on. Tokens, layout primitives, and CSS patterns stay stable. The engine can change.

Your design system

Airframe (tokens, layouts, patterns)

Angular · React · Vue · HTML · AI

Your framework provides the engine. Airframe provides the structure.

Most kits are shipped as framework packages.

  • @acme/ui is React components.
  • The Angular app reimplements the same button in Sass.
  • Spacing utilities diverge. Colour tokens get copied by hand.
  • Agents invent a third look because nothing in the repo is a shared contract.

Framework-agnostic components try to solve this by shipping one widget implementation plus bindings. That is a crowded category. And it still locks you to someone else’s component model.

Airframe starts one layer down. Same --af-* tokens. Same af-stack / af-btn contract. Your kit wraps that contract in <my-button> or <MyButton>. Different typed APIs. One look.

The markup is the design intent. React and Angular only differ in how they bind.

export function TeamHeader() {
return (
  <header className="af-inline af-justify-between">
    <h1>Team</h1>
    <button className="af-btn">Invite</button>
  </header>
);
}
@Component({
selector: 'app-team-header',
standalone: true,
template: `
    <header class="af-inline af-justify-between">
      <h1>Team</h1>
      <button class="af-btn">Invite</button>
    </header>
  `,
})
export class TeamHeader {}

Same classes. Same tokens. Different engine.

When the product already has a kit, the button is <my-button> / <MyButton>. That wrapper still renders af-btn. Product templates stay framework-native. The look stays Airframe. Full split: Use as much as you need.

SurfaceWhat staysWhat can change
ApplicationsTokens, layout grammar, pattern lookReact, Angular, Vue, HTML
TeamsOne --af-* sourceSeparate kit packages per framework
AgentsRules, class reference, MCPThe framework they emit
Design toolsSame token names and valuesFigma / Tokens Studio import today. Export from git to Figma Variables is on the roadmap.

Designers belong in this picture. Theme Studio already maps Tokens Studio, DTCG, and Figma Variables into Airframe CSS. Generating Figma Variables from the token spec is next, so Figma is a view of git, not the source of truth. Architecture: Design tokens as the source of truth.

You do not have to swallow a component zoo.

  1. Tokens only. Map --af-* to the brand. Keep your existing widgets.
  2. Layouts. af-stack, af-inline, af-grid in page templates.
  3. Patterns. af-btn, af-card, af-input as classes.
  4. Wrappers. Put those patterns inside the kit so product code never paints a second look.

Two palettes and two layout grammars is the failure mode. One source. One grammar.

Projects such as shared component kits with React, Vue, and Angular bindings answer “one implementation, three wrappers.”

Airframe answers “one structure, any implementation.” CSS-only. Zero runtime. Native HTML for behaviour (<button>, <dialog>, <details>). Your kit owns toast services, focus traps, and framework DI.

If you wanted a portable Dialog primitive with identical JS behaviour in every engine, that is a different layer. Sit it on Airframe. Do not replace the grammar with it.