Vanity is a design-system engine and TypeScript harness for CSS.
Vanity gives design-system authors inferred, composable, refactorable, and inspectable APIs while preserving the full capability and semantics of CSS. It emits ordinary CSS and keeps the browser—not a hidden styling runtime—responsible for live styling work.
🌟 Make Vanity the most delightful way to style with TypeScript.
- 🎨 Use all of CSS without giving up TypeScript. Author the platform’s names, grammar, selectors, at-rules, layers, custom properties, and future syntax with typed values and token handles. A raw standards lane remains available whenever CSS moves first.
- 🧩 Grow a system without breaking its foundations. Add tokens, axes, conditions, plugins, and utilities immutably; get loud, local conflicts instead of silent redefinition; then consolidate independent forks from the same base.
- ✂️ Remove the work that should have been inferred. Tokens flow from definition to use without copied paths, hand-built
var()calls, mirrored registries, or framework-specific glue. - ⚡ Ship ordinary CSS, not a client styling engine. Vanity compiles classes, custom properties, selectors, conditions, and code-split stylesheets that remain legible, portable, optimizable, and useful without Vanity at runtime.
- 🔎 Understand and evolve every decision confidently. Exact types, source-local diagnostics, editor DX, manifests, explanations, audits, and diffs retain one semantic identity from authoring through production.
- 🌐 Keep your application architecture yours. The core stays framework-independent; Vite, Vue, Nuxt, SSR, runtime controls, and the optional Hail policy layer are explicit integrations rather than a required stack.
npm install @mszr/vanityInstall vite when compiling Vanilla style modules. vue, nuxt, typescript, and @mszr/selenita are optional peers; add only the integrations and testing tools your project uses.
Create the design system in a plain TypeScript module. The open system defines and adds capabilities; the locked system styles with resolved handles.
// src/design/system.ts
import { createSystem } from '@mszr/vanity'
export const ds = createSystem()
.addTokens(ds => ({
color: {
brand: ds.tdef.color({
val: '#635bff',
mutable: true,
}),
canvas: '#ffffff',
},
space: {
md: ds.length.rem(1),
},
}))
.addConditions({
selected: '&[data-selected]',
})
.consolidate({
prefix: 'app',
root: ':root',
})Use the locked system in *.css.ts. Tokens are values: no copied string paths or manual var() calls.
// src/components/Card.css.ts
import { ds } from '../design/system'
export const card = ds.class({
color: ds.t.color.brand,
background: ds.t.color.canvas,
padding: ds.t.space.md,
selected: {
outline: `2px solid ${ds.t.color.brand}`,
},
})Configure the Vite plugin with the same plain system entry:
// vite.config.ts
import { vanityPlugin } from '@mszr/vanity/vite'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [vanityPlugin({
system: './src/design/system.ts',
cascade: ['vendor', 'app'],
})],
})Vanity evaluates the style module at build time and emits ordinary CSS: classes, custom properties, cascade layers, selectors, conditions, and at-rules. consolidate() itself performs no I/O and emits nothing, so tools can import the system directly.
Use the locked system to create classes, ordered fragments, selector rules, recipes, anatomies, atom sets, ports, keyframes, font faces, and raw CSS. Mutable tokens and activatable axes lower to declared browser-native slots; the optional runtime facade sets those slots and can create SSR-safe snapshots.
Vite projects manifests and portable system data from the same semantic contract. The CLI can inspect, explain, and diff those artifacts; the testing kit verifies emitted CSS, folding, rendered values, and editor DX.
const runtime = ds.runtime()
runtime.t.color.brand.$set('#16a34a')
runtime.t.color.brand.$unset()Start with the getting-started guide, then choose the contract that matches the work in front of you.
| Need | Documentation |
|---|---|
| Understand the product boundary | Vision, principles, and language |
| Define systems, tokens, conditions, and CSS | System authoring, tokens, conditions and axes, and styling/output |
| Build components or extensions | Recipes and anatomy, ports, and plugins and constructors |
| Integrate or operate a system | Vite/Vue/Nuxt integrations, runtime, and introspection/tooling |
| Test a consumer system or plugin | Testing kit |
| Use the optional opinionated layer | Hail |
| Browse everything | Documentation index |
This repository is the maintainer workspace around the publishable sdk/ package. Its workspace manual describes commands, CI, release rehearsal, demos, benchmarks, and evidence. Package consumers do not need the workspace to use Vanity.
Vanity is licensed under the GNU Affero General Public License v3.0.