Why Corn UI
One design system for your HTML and your React — what that means, who it suits, and what it doesn't do yet.
The idea
Most products are not one kind of page. There is a React app, and beside it a marketing site, a server-rendered admin, an email preview, a docs page, a prototype someone built in plain HTML. Corn UI is built so all of them can share one look and one set of behaviours, without each one having to be written in the same framework.
It does that by putting things in layers:
-
Classes first. Every component is a set of CSS classes and
data-*attributes. About half of the library needs no JavaScript at all: a button, a grid, a table, a switch, a timeline are markup and a stylesheet.<button class="corn-button" data-level="primary">Save</button> -
A small controller where behaviour is needed. A
create*function adds what classes cannot — state, listeners, keyboard handling — to that same markup. Nothing is re-rendered; it works on whatever page the HTML came from. -
React from the same source. The React components render the same classes and attributes, and their props are documented from the same source as the vanilla options, so the two cannot quietly drift apart.
A Rails view, a static page and a Next.js app can all use Corn UI and look the same, and moving a screen from one to another does not mean restyling it.
What you get
- Accessible interactive widgets. Dialogs trap focus and make the page behind them inert; menus, tabs, the combobox and navigation trees are driven by the keyboard. The docs site itself is checked on every build for unnamed form controls.
- Small, with no runtime dependencies. The core JavaScript is about 20 KB
gzipped and its stylesheet about 13 KB. Nothing is pulled in alongside it;
the only third-party code anywhere is the markdown parser inside
@corndev/ui-markdown. - Server Component–safe React. Each component that needs the client carries
its own
'use client', so importing the package from a Server Component does not drag the rest in with it. A real Next.js build checks this on every release. - Theming with CSS custom properties. Colours, spacing, radii and control heights are tokens you override in a stylesheet; dark mode is one attribute. See Theming.
- Typed. Every package ships TypeScript declarations.
- No build step if you don’t want one. The CDN build loads with a
<script>and a<link>, with integrity hashes for each file. - Ready for AI-assisted work.
llms.txtdescribes every component, option and prop for a coding assistant, and@corndev/eslint-pluginchecks JSX against the props each installed component actually accepts, so a mistyped or invented prop is caught before it renders. - State and data, too, if you want them.
@corndev/storeand@corndev/queryare small, dependency-free packages for app state and server data. They work with or without the UI library.
Who it suits
- Teams with more than one kind of front end — server-rendered pages and a React app that should look like one product.
- Pages that should work before, or without, JavaScript. Much of the library is plain HTML and CSS, and the controllers enhance markup that is already there.
- React apps using Server Components, where a component library that marks everything as client code costs you the point of them.
- Small pages and prototypes that want a finished look from a CDN link.
What it doesn’t do yet
Corn UI is in beta, and it is better to know this before you start:
- No date picker, data grid or charts yet.
- React is the only framework layer. Anything else uses the HTML and the vanilla controllers directly.
- It is not built on a utility-class framework. You style it with its tokens and your own CSS.
- It is young. The API is close to what 1.0 will ship, but a beta can still change; every breaking change is listed in the changelog with what to do.
If those fit, start with Installation.