Navigation

NewAn MCP server for your AI agents

A markup-driven CSS orchestration language for developers and AI agents.

Get started
npm create @master/css@2.0.0

Design system

Build modern interfaces from one class vocabulary.

Themes, tokens, wide-gamut color, layout and motion are all written as classes, and the CSS they generate stays predictable.

Define your theme tokens

Light and dark, same markup

Modes swap token values, not class names. Drag the divider to see which value is in use.

Tokens, defined once

Define color, spacing, radius and type once in @theme; utilities, components and modes all read from them.

@theme {  --font-family-sans: "Inter";  --spacing-md: 1rem;   /* p-md */  --spacing-lg: 1.5rem; /* p-lg */  --radius-xl: 0.75rem; /* r-xl */  /* bg-surface-base */  --color-surface-base: light-dark(    var(--color-zinc-0),    var(--color-zinc-95)  );}

Layout and motion, together

Grid spans, responsive layouts, animation and view transitions, written right beside the markup they style.

Click a photo to preview the transition.

Native CSS layers

Utilities sit in a later layer than components, so a class in markup wins without !important.

Wide-gamut color

P3 palettes on a predictable tier scale, from deep anchors to bright accents beyond sRGB.

Editor

Dense class strings, still readable.

The language service completes classes from your manifest, shows the CSS behind each class on hover and marks colors in place.

Use the arrow keys to read the file.

<article class="grid gap-lg p-xl b-solid b(1) b-line-divider r-2xl bg-surface-raised shadow-sm">
<header class="flex items-center justify-between gap-md">
<h3 class="text-lg font-medium fg-text-strong">Usage alerts</h3>
<a class="text-sm font-medium fg-blue-60 fg-blue-70:hover@sm" href="/settings/alerts">Manage</a>
</header>
<p class="text-sm">Email the team before a project reaches its monthly limit.</p>
<ul class="grid gap-xs p-md r-lg bg-surface-base grid-cols(2)@md">
<li class="flex items-center justify-between gap-sm text-sm">
Builds
<span class="px-xs r-md text-xs font-semibold bg-blue-60/.1 (color:#4f46e5)">80%</span>
</li>
<li class="flex items-center justify-between gap-sm text-sm">
Bandwidth
<span class="px-xs r-md text-xs font-semibold bg-surface-raised fg-text-muted">42%</span>
</li>
</ul>
</article>
fg-blue-70:hover@sm CSS
@layer theme {  :root,  :host {    --color-blue-70: oklch(46.26% .3057 266.7)  }}@layer utilities {  @media (width >= 52.125rem) {    .fg-blue-70\:hover\@sm:hover {      color: var(--color-blue-70)    }  }}
Token --color-blue-70
Completions30
fg-text-amber
fg-text-beryl
fg-text-blue
fg-text-body
fg-text-brown
fg-text-crimson
fg-text-cyan
fg-text-disabled

:

Rendering

One syntax. Every delivery path.

Ship static CSS by default, pre-render it into HTML or generate it in the browser. Your classes stay the same.

Compare rendering modes
index.htmlTemplate
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Static rendering</title>
<link rel="stylesheet" href="/base.css">
<link rel="stylesheet" href="">
</head>
<body>
<article class="demo p-lg r-xl
bg-amber-10 shadow-sm">
<h1>Static rendering</h1>
…
</article>
<script src="/app.js"></script>
</body>
</html>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Progressive rendering</title>
<link rel="stylesheet" href="/base.css">
<style id=""
data-master-css-hydration-manifest="…">
/* … */
</style>
</head>
<body>
<article class="demo p-lg r-xl
bg-amber-10 shadow-sm">
<h1>Progressive rendering</h1>
…
</article>
<script src="/app.js"></script>
</body>
</html>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Runtime rendering</title>
<link rel="stylesheet" href="/base.css">
<script type="module" src="/main.js"></script>
<style id="">
/* CSSOM ↓ */
</style>
</head>
<body>
<article class="demo p-lg r-xl
bg-amber-10 shadow-sm">
<h1>Runtime rendering</h1>
…
</article>
<script src="/app.js"></script>
</body>
</html>
CSSCSSOMCSSOM
/* Shared styles … */
@layer utilities {
.bg-amber-10 {
background-color: var(--color-amber-10);
}
.r-xl { border-radius: var(--radius-xl); }
.shadow-sm { box-shadow: var(--shadow-sm); }
.p-lg { padding: var(--spacing-lg); }
}
/* Shared styles … */
@layer utilities {
.bg-amber-10 {
background-color: var(--color-amber-10);
}
.r-xl { border-radius: var(--radius-xl); }
.shadow-sm { box-shadow: var(--shadow-sm); }
.p-lg { padding: var(--spacing-lg); }
}
/* Shared styles … */
@layer utilities {
.bg-amber-10 {
background-color: var(--color-amber-10);
}
.r-xl { border-radius: var(--radius-xl); }
.shadow-sm { box-shadow: var(--shadow-sm); }
.p-lg { padding: var(--spacing-lg); }
}
PreviewLive

Scan complete class names in your source.Write the matching rules to app.css.Load the stylesheet before the page is painted.Reuse the rule already shipped in app.css.

Read the classes in the server-rendered HTML.Embed the first-load CSS in the page.Paint with the CSS that came with the HTML.Start the deferred engine for an uncovered class.

Read the page’s classes in the browser.Start the runtime and create a stylesheet.Generate and apply the rules in the browser.Insert the new rule into the browser stylesheet.

CSS size

Measured on real documentation pages.

The CSS each page loads, raw and with Brotli. Master CSS adds only the utilities a page uses; the rest is each site’s own styles.

View benchmark details

CSS per documentation page · 2026-11-04

  1. Master CSS
    110.4 kB
  2. Angular
    151.8 kB 1.4×
  3. Vue.js
    186.3 kB 1.7×
  4. Material UI
    277.4 kB 2.5×
  5. Bootstrap
    294 kB 2.7×
  6. Next.js
    479.9 kB 4.3×
  7. Tailwind CSS
    657.7 kB 6.0×
0200400600800 kB

Lint

Lint classes against your project.

ESLint in your editor, the CLI in your scripts and the MCP server for agents check classes with the same rules and fixes.

See every lint rule
button.html ESLint Ready
<button class="inline-flex (color:12px)">
Save changes
</button>

@master/css/no-invalid-classes 1:28

CLI @master/css-cli Ready
$ npx @master/css-cli lint --format stylish1:28error@master/css/no-invalid-classes
MCP server @master/css-mcp Ready
→ mastercss_lint_content button.html"ruleId": "no-invalid-classes","severity": "error","loc": { "start": { "line": 1, "column": 28 } }

AI agents

Agents check their own changes.

The MCP server gives coding agents your manifest and lint rules, so they check their own edits and hand you fixes as diffs.

Set up the MCP server
Session@master/css-mcp
plan-card.html
  1. Style the plan card with our spacing and color tokens.

  2. I will look up the spacing tokens in the project manifest first.

  3. mastercss_manifest_query 12 tokens
    { "kind": "token", "namespace": "spacing" } spacing-4xs … spacing-5xl
  4. Editplan-card.html+3 −3
  5. mastercss_inspect_class matched
    { "className": "bg-surface-raised" } background-color: var(--color-surface-raised)
  6. mastercss_lint_project 4 problems
    { "patterns": ["plan-card.html"] } 4 warnings, 4 fixable
  7. mastercss_preview_fixes 1 file changed
    { "patterns": ["plan-card.html"] } confirmToken "Vq3zK8…Ug6J"
  8. The fix sorts the classes and removes mt-md, which mt-sm overrides. Apply it?

  9. Apply it.

  10. mastercss_apply_preview Applied
    { "confirmToken": "Vq3zK8…Ug6J" } Hash matched, file written
  11. mastercss_lint_project No problems
    { "patterns": ["plan-card.html"] } 0 problems
  12. Applied. plan-card.html passes lint with no problems.

1<article class="grid gap-md p-lg r-xl bg-surface-raised">
2 <h3 class="mt-sm text-xl font-medium">Pro plan</h3>
3 <p class="text-sm fg-text-muted">Unlimited projects</p>
4</article>
Output mastercss_lint_project

No problems

plan-card.html
Hash matched, file writtensha256 4e0a1aab…c9c0

Workflow

Works with your framework and build.

One project manifest drives the CSS of every integration, monorepo app and route, and a snapshot comparison shows what a change touches.

Install for your framework

Framework integrations

Every framework integration and the CLI load the same project manifest, so builds and editors agree.

index.css

Monorepo-aware

Each file follows its nearest project, so one class can resolve differently per app.

index.css

Route-level styles

Route stylesheets use shared tokens, mixins and custom media without copying global rules.

index.css
.hero { display: grid; gap: var(--spacing-5xl); @media (--md) { grid-auto-flow: column; }}
pricing.css
.plan { padding: var(--spacing-lg); @apply --raised; @media (--md) { padding: var(--spacing-5xl); }}
blog.css
.post { max-width: 42rem; padding: var(--spacing-lg); @media (--md) { @apply --raised; }}
--spacing-5xl--spacing-lg--raised--md

Trace a change

Change a token and compare snapshots to see the classes, files and outputs it reaches.

Start with one class string, then grow into a design system.

Get started
npm create @master/css@2.0.0