LSD Framework

Substrate model

How Foundry treats tokens as the primary contract.

Overview

There is a recurring debate in design systems work — should the system be a library, or a compiler? Both camps have good arguments. I want to suggest a third position: the system is a substrate.

A library exposes building blocks. A compiler enforces correctness. A substrate is the medium itself — the thing every other artefact rests on. Tokens are a substrate. The DOM is a substrate. CSS variables are a substrate.

Why this matters

If you treat your design system as a library, you ship components. If you treat it as a compiler, you ship rules. If you treat it as a substrate, you ship a vocabulary. Components and rules become emergent, not authored.

The interface of a design system is not its components — it is the names of its tokens.

Names compose. Names travel. Names can be reasoned about by a tool, an LLM, or a junior engineer with the same effort. Components, on the other hand, want to be subclassed, customised, and eventually forked. They are bad at travel.

A practical example

Consider a button. As a library, you ship Button. As a compiler, you ship a button schema. As a substrate, you ship --button--padding-x, --button--padding-y, --button--radius — and the button assembles itself.

Now, an agent reading your codebase can change padding without parsing JSX. A junior dev can redesign the button by editing three lines. Your design partner in another studio can preview their version of the button in your app, without a build step. That is what substrate buys you.

Where this falls down

Substrates are bad at complex interaction. The moment a button needs to manage focus rings, keyboard navigation, ARIA labelling, and async loading state, you have a component on your hands whether you wanted one or not.

The trick is to be honest about which layer you are working at. Substrate first. Components when the cost of duplication exceeds the cost of indirection. Compilers when the team is large enough to absorb the operational cost.

API

The substrate API is intentionally tiny. Three calls: register(), resolve(), and emit(). Everything else is a wrapper.

Build on Foundry

Read the quickstart and ship in an afternoon.

Quickstart