Skip to content
v1.26 · MIT · React 18+ · no roadmap

A themeable React design system. Use it or don’t.

I built it for my own projects. 91 components, five themes, every colour pairing audited against WCAG AA — because I’m the one who has to look at it. Set one attribute and everything repaints, including the components you wrote.

bun add @mikenotthepope/substrateui
pick a theme. this page is the demo. yes, that’s a lot of themes for one person.
Tint rampstints mixed in oklab · 25 / 50 / 75 / 100%
Primary--primary
Secondary--secondary-fill
Neutral--foreground
Live

The same markup in every theme.

Nothing on the left knows which theme it is in. The map on the right is the only thing that changed — and it is the whole theme, not an excerpt.

Project settings
Draft

Lowercase, no spaces.

Preview deployments

Build every pull request.

theme.ts
import { createTheme, ThemeRegistry } from 'substrateui'

const proof = createTheme({
  name: 'proof',
  light: { primary: 'oklch(0.520 0.133 232)' },
  dark:  { primary: 'oklch(0.750 0.115 233)' },
})

// Wrap once — every component below repaints.
<ThemeRegistry themes={[proof]} defaultTheme="proof">
  <App />
</ThemeRegistry>

A theme sets palette, motion curve and corner radius. Light and dark come with it.

Fit

Who it's for

Me, mostly. If you recognise yourself below, help yourself — every claim is checked by the build, not by me.

More than one brand

A theme is a token map, and no component ever learns its name. Adding the sixth palette costs a file, not a refactor — and light and dark come with it.

Accessibility as a requirement

35 colour pairings per theme are checked against WCAG AA on every commit, and a failing ratio fails the build. Base UI handles focus, dismissal and ARIA underneath.

Owning your own stack

MIT, no runtime service, no account. React 18+ and Tailwind v4 are the only hard peers — Next and next-themes are optional, so it is not a Next.js-only system.

Job docket

What you get, roughly

ItemValueDetail
Components91atomic Button through organism App Shell
Themes5proof · substrate · lava · tundra · plum
Audited pairs35per theme, light and dark. A failing ratio fails the build.
ColourOKLCHperceptually uniform ramps, so contrast is computed, not eyeballed
PrimitivesBase UIfocus management, dismissal and ARIA are handled
CSSTailwind v4@theme inline — no config file
Peer depsreact ≥ 18tailwindcss ≥ 4 · next and next-themes optional
LicenceMITfork it, ship it, sell it
SupportNoneissues welcome, replies not promised
Users1hi

Bring your own theme

Five themes ship, but the set is open. A theme is a token map — no component ever learns its name.