@mszr/vanity
@mszr/vanity
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.
North Star
🌟 Make Vanity the most delightful way to style with TypeScript.
Highlights
- 🎨 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 escape 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-side style graph. 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.
Install
npm install @mszr/vanity
Install 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.
Quick start
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({
compiler: {
system: './src/design/system.ts',
},
autoImports: {
shared: '$system', // `ds` in both style and application modules
app: ['core'],
},
})],
})
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.
What you can build
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 controller sets those slots and can create SSR-safe snapshots.
The Vite integration projects the manifest 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()
Documentation
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 |
Repository and development
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.
License
Vanity is licensed under the GNU Affero General Public License v3.0.
Related Packages
Provides a design token-powered UI component library and styling system for Nuxt...
Northwest University marketing design system as a Nuxt 4 layer — tokens, CSS com...
Cross-framework design system tokens, Tailwind plugin, and variants for CUI
Version History
| Version | Released | Vue | License |
|---|---|---|---|
| 0.8.1 | ^3.5.39 | AGPL-3.0-only | |
| 0.8.0 | ^3.5.39 | AGPL-3.0-only | |
| 0.7.0 | ^3.5.39 | AGPL-3.0-only | |
| 0.6.1 | ^3.5.39 | AGPL-3.0-only | |
| 0.6.0 | ^3.5.39 | AGPL-3.0-only | |
| 0.5.1 | ^3.5.39 | AGPL-3.0-only | |
| 0.5.0 | ^3.5.39 | AGPL-3.0-only | |
| 0.4.0 | ^3.5.39 | AGPL-3.0-only | |
| 0.3.0 | ^3.5.39 | AGPL-3.0-only | |
| 0.2.0 | ^3.5.39 | AGPL-3.0-only | |
| 0.1.1 | ^3.5.39 | AGPL-3.0-only | |
| 0.1.0 | ^3.5.39 | AGPL-3.0-only |