Meta’s Astryx Brings a CLI and MCP Server to an Open-Source React Design System Agents Can Read

Meta’s Astryx Brings a CLI and MCP Server to an Open-Source React Design System Agents Can Read

Meta released Astryx, an open-source React design system built on StyleX. It pairs a CSS-variable theme cascade with a CLI and MCP server, so both engineers and AI agents build using the same API. The project is in Beta, MIT-licensed, and grew inside Meta over eight years. The post Meta’s Astryx Brings a CLI and MCP Server to an Open-Source React Design System Agents Can Read appeared first on MarkTechPost .

MarkTechPost ·Asif Razzaq ·

Meta released Astryx this week. It is an open-source design system, currently in Beta. The project grew inside Meta’s monorepo over eight years. Astryx is built on React and StyleX. StyleX is Meta’s compile-time CSS engine.

• Astryx is Meta’s open-source, agent-ready React design system, now in Beta.

• It pairs StyleX styling with a CSS-variable theme cascade and ten themes.

• A CLI and MCP server lets AI agents scaffold and document UIs.

• It is production-tested inside Meta but young as a public project.

What is Astryx

Astryx is a component library and a system around it. It provides foundations, components, templates, and themes. Foundations cover typography, color, layout, and accessibility. The official repository documents more than 90 React components. Meta’s docs site counts over 150. Components ship with built-in spacing, dark mode, and flexible styling. Templates compose full pages like dashboards, settings, and forms. The license is MIT. TypeScript makes up about three-quarters of the codebase.

The styling layer is worth understanding. StyleX compiles styles to static, atomic CSS at build time. Meta open-sourced StyleX at the end of 2023. It powers Facebook, Instagram, WhatsApp, and Threads. External companies like Figma and Snowflake also use it.

Two design choices stand out. First, internals are open. All primitives are exported and composable, not hidden. You can compose at any level. Second, spacing is automatic. Astryx calls this context-aware spacing compensation. It eliminates ‘double padding’ issues without manual fixups.

The ‘Agent Ready’ Part

This is the main difference from other design systems. Astryx ships docs and tooling that AI agents can read. Components carry JSDoc annotations with composition hints. A CLI exposes the same API a developer uses. There is also an MCP server. MCP is the Model Context Protocol. Agents use it to scaffold, browse, and document.

The CLI is called via astryx or the shorthand xds. One feature is really important for automation. The CLI returns a self-describing manifest as JSON. It lists every command, argument, flag, and response type. Compareing it to an OpenAPI spec for the CLI. So an agent need not scrape --help text. It reads one structured payload instead.

Copy CodeCopiedUse a different Browser

npx astryx component Button # full docs for a component

npx astryx template dashboard # emit full page source

npx astryx manifest --json # machine-readable command spec

Themes and the CSS-Variable Cascade

Astryx ships ten ready-made themes. They are named default, neutral, daily, butter, chocolate, matcha, stone, gothic, brutalist, and y2k. All are fully customizable. Theming uses a CSS variable cascade. You change the variables, and every component restyles. Component code stays untouched.

The interactive demo below shows this directly. Pick a theme and watch the tokens update live.

#ax *{box-sizing:border-box}

--bg:#ffffff;--panel:#f7f8fb;--ink:#161a21;--muted:#5c6573;--line:#e6e9ef;

--accent:#2563eb;--accent-soft:#eef3ff;--brand:#76B900;

--mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;

--sans:'Inter',system-ui,-apple-system,Segoe UI,Roboto,sans-serif;

font-family:var(--sans);color:var(--ink);background:var(--bg);line-height:1.45;

max-width:920px;margin:0 auto;border:1px solid var(--line);border-radius:16px;

overflow:hidden;display:flex;flex-direction:column;box-shadow:0 6px 30px rgba(16,24,40,.06);

#ax a{color:var(--accent);text-decoration:none}

#ax a:hover{text-decoration:underline}

/* top bar: brand + section tabs */

.deck-top{display:flex;align-items:center;gap:14px;padding:11px 16px;

border-bottom:1px solid var(--line);background:

radial-gradient(700px 120px at 0% -60%,#eef3ff,transparent 70%),var(--bg)}

.brand{font-weight:800;font-size:15px;letter-spacing:-.01em;white-space:nowrap}

.brand span{font-weight:600;font-size:11px;color:var(--muted)}

.tabs{display:flex;gap:3px;margin-left:auto;flex-wrap:wrap;justify-content:flex-end}

.tab{font:600 11.5px/1 var(--mono);color:var(--muted);background:transparent;border:1px solid transparent;

border-radius:8px;padding:6px 8px;cursor:pointer;display:flex;gap:5px;align-items:center}

.tab:hover{background:var(--panel);color:var(--ink)}

.tab[aria-current=true]{background:var(--accent);color:#fff}

.tab .tl{font-family:var(--sans)}

/* stage holds slides; fixed height = slide */

.stage{position:relative;height:524px}

.slide{position:absolute;inset:0;overflow:auto;padding:20px 24px;

opacity:0;visibility:hidden;transform:translateY(8px);transition:opacity .26s ease,transform .26s ease}

.slide.is-active{opacity:1;visibility:visible;transform:none}

.slide::-webkit-scrollbar{width:8px}.slide::-webkit-scrollbar-thumb{background:#d8dde5;border-radius:8px}

.knum{font:700 11px/1 var(--mono);color:var(--accent);letter-spacing:.07em}

.slide h2{margin:7px 0 5px;font-size:20px;letter-spacing:-.01em;font-weight:750}

.lead{margin:0 0 12px;color:#2a323d;font-size:13.5px;max-width:74ch}

.lead .m{color:var(--muted)}

.note{font-size:11.5px;color:var(--muted);margin-top:10px;display:flex;gap:6px;align-items:flex-start}

.note b{color:var(--accent);font-weight:700;white-space:nowrap}

/* bottom controls */

.deck-bot{display:flex;align-items:center;gap:12px;padding:10px 16px;border-top:1px solid var(--line);background:var(--panel)}

.arrow{width:30px;height:30px;border-radius:8px;border:1px solid var(--line);background:#fff;color:var(--ink);

font-size:16px;cursor:pointer;display:flex;align-items:center;justify-content:center}

.arrow:hover{border-color:var(--accent);color:var(--accent)}

.arrow:disabled{opacity:.4;cursor:default;border-color:var(--line);color:var(--muted)}

.counter{font:600 12px/1 var(--sans);color:var(--muted)}

.counter b{color:var(--ink)}

.progress{flex:1;height:4px;background:var(--line);border-radius:999px;overflow:hidden}

.progress i{display:block;height:100%;background:var(--accent);border-radius:999px;transition:width .26s ease}

.mtp{font:700 11px/1 var(--sans);color:var(--brand);white-space:nowrap}

/* facts */

.facts{display:grid;grid-template-columns:repeat(4,1fr);gap:9px;margin-top:6px}

.fact{background:var(--panel);border:1px solid var(--line);border-radius:11px;padding:12px}

.fact b{display:block;font-size:20px;font-weight:800;letter-spacing:-.02em}

.fact span{font-size:11px;color:var(--muted)}

.pills{display:flex;flex-wrap:wrap;gap:7px;margin-top:12px}

.pill{font:600 11.5px/1 var(--sans);padding:6px 10px;border:1px solid var(--line);border-radius:999px;background:#fff}

.pill.lnk{background:var(--accent);border-color:var(--accent)}

#ax a.pill.lnk{color:#fff}

/* cascade widget (scoped vars) */

#cas{--c-bg:#f7f8fa;--c-surface:#fff;--c-text:#1b1f24;--c-muted:#5b6471;--c-border:#e3e7ec;

--c-primary:#2563eb;--c-pt:#fff;--c-accent:#eef3ff;--c-radius:10px;--c-radius-sm:6px;--c-space:12px;

--c-font:var(--sans);--c-weight:600}

.chips{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:11px}

.chip{cursor:pointer;border:1px solid var(--line);background:#fff;color:var(--ink);

font:600 11.5px/1 var(--sans);padding:6px 10px;border-radius:999px;display:flex;gap:6px;align-items:center}

.chip[aria-pressed=true]{border-color:var(--accent);box-shadow:0 0 0 2px var(--accent-soft)}

.dot{width:10px;height:10px;border-radius:50%}

.casgrid{display:grid;grid-template-columns:1.2fr .85fr;gap:12px}

.prev{background:var(--c-surface);color:var(--c-text);font-family:var(--c-font);border:1px solid var(--c-border);

border-radius:var(--c-radius);padding:13px;display:flex;flex-direction:column;gap:var(--c-space);transition:.2s}

.prev .r{display:flex;flex-wrap:wrap;gap:8px;align-items:center}

.b{font:inherit;font-weight:var(--c-weight);font-size:12.5px;cursor:pointer;padding:7px 12px;border-radius:var(--c-radius-sm);border:1px solid transparent}

.b.p{background:var(--c-primary);color:var(--c-pt)}.b.s{background:var(--c-surface);color:var(--c-text);border-color:var(--c-border)}

.bd{font:700 10.5px/1 var(--sans);padding:4px 8px;border-radius:999px;background:var(--c-accent);color:var(--c-primary)}

.in{font:inherit;font-size:12.5px;padding:7px 10px;width:100%;border:1px solid var(--c-border);border-radius:var(--c-radius-sm);background:var(--c-surface);color:var(--c-text)}

.mc{background:var(--c-surface);border:1px solid var(--c-border);border-radius:var(--c-radius);padding:11px;display:flex;gap:10px;align-items:center}

.av{width:32px;height:32px;border-radius:50%;background:var(--c-primary);color:var(--c-pt);display:flex;align-items:center;justify-content:center;font-weight:700;font-size:13px;flex:0 0 32px}

.mc .t{font-weight:600;font-size:12.5px}.mc .d{color:var(--c-muted);font-size:11px}

.csw{width:38px;height:22px;border-radius:999px;background:var(--c-border);position:relative;cursor:pointer;flex:0 0 38px}

.csw[aria-checked=true]{background:var(--c-primary)}

.csw::after{content:"";position:absolute;top:3px;left:3px;width:16px;height:16px;border-radius:50%;background:#fff;transition:.2s;box-shadow:0 1px 2px rgba(0,0,0,.25)}

.csw[aria-checked=true]::after{transform:translateX(16px)}

.tok{background:#fff;border:1px solid var(--line);border-radius:11px;padding:11px}

.tok h4{margin:0 0 8px;font:700 10px/1 var(--mono);letter-spacing:.06em;color:var(--muted);text-transform:uppercase}

.trow{display:flex;justify-content:space-between;align-items:center;font-size:11px;padding:4px 0;border-bottom:1px dashed var(--line)}

.trow:last-child{border:0}.trow code{font-family:var(--mono);color:var(--muted)}

.tv{font-family:var(--mono);font-size:10.5px;display:flex;align-items:center;gap:5px}

.swatch{width:12px;height:12px;border-radius:4px;border:1px solid var(--line)}

.sld{margin-top:11px}.sld label{display:flex;justify-content:space-between;font:600 11.5px/1 var(--sans);color:var(--muted)}

.sld input{width:100%;margin-top:6px;accent-color:var(--accent)}

/* spacing widget */

.spctrls{display:flex;flex-wrap:wrap;gap:16px;align-items:center;margin-bottom:12px}

.tgrow{display:flex;align-items:center;gap:9px;font:600 12.5px/1 var(--sans)}

.tg{width:42px;height:24px;border-radius:999px;background:#cfd5de;position:relative;cursor:pointer}

.tg[aria-checked=true]{background:var(--accent)}

.tg::after{content:"";position:absolute;top:3px;left:3px;width:18px;height:18px;border-radius:50%;background:#fff;transition:.2s;box-shadow:0 1px 2px rgba(0,0,0,.25)}

.tg[aria-checked=true]::after{transform:translateX(18px)}

.spstage{display:grid;grid-template-columns:1fr auto;gap:14px;align-items:center}

.outer{background:#dbe4f7;box-shadow:inset 0 0 0 1px #9db4e6;border-radius:12px}

.inner{background:#bcd0f3;box-shadow:inset 0 0 0 1px #6f93da;border-radius:9px}

.content{background:#fff;border:1px solid var(--line);border-radius:7px;padding:11px;text-align:center;font-size:12px}

.readout{background:#fff;border:1px solid var(--line);border-radius:11px;padding:13px;min-width:170px}

.readout .big{font-size:28px;font-weight:800;letter-spacing:-.02em}

.readout .big.good{color:#1f8f46}.readout .big.bad{color:#c0392b}

.readout .lab{font-size:11px;color:var(--muted)}

.readout .calc{margin-top:7px;font:600 11px/1.5 var(--mono);color:var(--muted)}

/* code + tabs */

.ctabs{display:flex;gap:4px}

.ctab{font:600 11.5px/1 var(--sans);padding:6px 11px;border:1px solid var(--line);border-bottom:0;border-radius:8px 8px 0 0;background:var(--panel);color:var(--muted);cursor:pointer}

.ctab[aria-selected=true]{background:#0f1420;color:#dfe7f5;border-color:#0f1420}

pre.code{margin:0;background:#0f1420;color:#e7edf7;border-radius:0 9px 9px 9px;padding:13px 15px;overflow-x:auto;font:12.5px/1.55 var(--mono)}

.code .k{color:#7cc4ff}.code .s{color:#9ae6a4}.code .c{color:#7a899e}.code .f{color:#f0c674}

.paneprev{border:1px solid var(--line);border-top:0;border-radius:0 0 9px 9px;background:#fff;padding:13px;display:flex;gap:9px;flex-wrap:wrap;align-items:center}

/* terminal */

.term{background:#0f1420;border-radius:11px;overflow:hidden;border:1px solid #1d2738}

.tbar{display:flex;align-items:center;gap:6px;padding:8px 11px;background:#161d2c;border-bottom:1px solid #1d2738}

.tbar i{width:10px;height:10px;border-radius:50%}

.ttitle{margin-left:7px;font:600 11px/1 var(--mono);color:#8a98ad}

.cmds{display:flex;flex-wrap:wrap;gap:6px;padding:10px 11px;background:#121828;border-bottom:1px solid #1d2738}

.cmd{font:600 11.5px/1 var(--mono);color:#cfe0ff;background:#1b2740;border:1px solid #28385a;border-radius:7px;padding:6px 9px;cursor:pointer}

.cmd[aria-pressed=true]{background:#243a5e;border-color:#3b5d91;color:#fff}

pre.out{margin:0;padding:13px 15px;color:#d6e0f0;font:12px/1.5 var(--mono);white-space:pre-wrap;height:188px;overflow:auto}

.out .p{color:#76e0a0}.out .d{color:#7a899e}.out .y{color:#f0c674}.out .b{color:#7cc4ff}

@media(max-width:680px){

.stage{height:600px}

.tab .tl{display:none}

.brand span{display:none}

.facts{grid-template-columns:repeat(2,1fr)}

.casgrid,.spstage{grid-template-columns:1fr}

Astryx · interactive explainer

01 · OVERVIEW

What Astryx is

An open-source React design system from Meta — foundations, components, templates, and themes. Built on React and StyleX, Meta’s compile-time CSS engine. It ships pre-built CSS, so no build plugin is required. Currently in Beta.

8 yrsbuilt inside Meta

13,000+apps it powers

150+components (docs site)

10ready-made themes

github.com/facebook/astryx

MIT license

NoteThe GitHub repo states “over 90 components”; Meta’s docs site counts 150+. Both come from official Astryx sources.

02 · THEMING

The CSS-variable cascade

Themes are a cascade of CSS variables (tokens). Change the variables and every component restyles — component code never changes. Pick a theme:

Astryx Card

tokens drive every style

Active tokens

–spacing scale 12px

IllustrativeThe cascade mechanism is exactly how Astryx themes work; per-theme token values are representative.

03 · LAYOUT

Automatic spacing — the “double padding” fix

Nest a padded box in another and the gaps stack; you normally strip padding by hand. Astryx’s context-aware spacing compensation keeps the edge gap consistent. Toggle it — the gap is measured from the rendered DOM.

Compensation: ON

container padding 16px

Measured edge gap

IllustrativeThe gap is read from the real DOM. The rule here stands in for Astryx’s internal logic.

04 · ARCHITECTURE

Open internals you can compose and eject

Astryx exports its primitives instead of hiding them, so you compose at any level. When a component is close but not exact, eject its source with the CLI and edit it directly.

Use a component

Eject to customize

import {Button} from '@astryxdesign/core/Button';

import {Badge} from '@astryxdesign/core/Badge';

export default function Toolbar() {

compartilhar: