A First Look at Astryx, Meta's Design System
Astryx, Meta’s open-source design system, pairs 150+ React components with themes, CLI setup, customization levels, and shadcn/ui and Base UI comparisons.
Astryx is Meta’s open-source rebuild of the design system that grew inside the company, announced on the Astryx blog on 18 June 2026 and published as a public beta under the MIT license, shipping more than 150 accessible React components, seven ready-made themes, templates and a CLI, built on React 19 or later and StyleX.
If you have shipped on MUI, you know one version of the trade: the components work, and then you spend a sprint fighting a theme object to make a button stop looking like someone else’s button. If you own shadcn/ui source, you know the other: forty component files in your repo, entirely yours, with no upstream to pull a focus-management fix from.
Meta’s pitch is that Astryx sits between those. The feature list is easy to find; what actually determines the cost of adopting it is the five-rung customization ladder and where on that ladder your team ends up living. This piece covers what Astryx is, how you install and consume it, how theming works, what each rung of that ladder costs you, and where it lands next to shadcn/ui and Base UI.
Key Takeaways
- Astryx needs React 19 or newer, and
@astryxdesign/corenamesreact,react-domand@stylexjs/stylexas peer dependencies. - Astryx ships two distribution paths: import the pre-compiled stylesheets, or build from TypeScript and StyleX source so your bundler emits CSS only for components you import.
- Customization escalates through five rungs, and only the last one, swizzling a component’s source into your repo, takes you off the shared upgrade path.
- Components accept both a typed
xstyleprop and a plainclassName, and the pre-compiled path adds nothing to your build: no bundler plugin, no PostCSS, no Babel config. - Astryx is still a public beta on 0.x releases with no stable line, which makes API churn a live cost.
What Is Astryx?
Astryx is a component library with a whole system wrapped around it: typed React components shipped next to pre-compiled CSS, plus theming at the brand level, dark mode, page templates and a CLI, all distributed as one set of packages. Meta’s technical write-up presents it as the open-source rebuild of a system that grew inside the company for eight years, reached more than 13,000 products, and took roughly half of its updates from the builder community there. Styles are authored with StyleX, Meta’s compiler that turns style objects into atomic, collision-free CSS at build time, which matters if your objection to CSS-in-JS is runtime cost: there is no style engine running in the browser.
The CLI is where most work with the project happens, for people and machines alike. Component docs, design tokens, page templates, theming tools and upgrade codemods all come out of it, whether you call it from a terminal, read its typed JSON output or import its functions, and agents and build tools go through the same API. The project’s own framing of this as “AI-fluent” and agent-ready is positioning, not a measured result; the evaluation harness Meta describes has no published results in either announcement post.
How Do You Actually Consume Astryx?
React 19 is the floor: @astryxdesign/core lists react and react-dom at 19.0.0 or above as peer dependencies. That is the first gate. The second is maturity: @astryxdesign/core publishes on a 0.x line on npm, and @astryxdesign/vega and @astryxdesign/charts ship real builds only under the @canary dist-tag, with their latest tag still pointing at a placeholder release.
Install the core package, a theme package and the StyleX peer, with the CLI as a dev dependency:
npm install @astryxdesign/core @astryxdesign/theme-neutral @stylexjs/stylex
npm install -D @astryxdesign/cli
npx @astryxdesign/cli init
The init step writes Astryx’s component index into your AGENTS.md or CLAUDE.md, which you can skip if no agent touches the repo. On the simple path you then import three stylesheets, in order, and wrap the app in a theme provider:
@import '@astryxdesign/core/reset.css';
@import '@astryxdesign/core/astryx.css';
@import '@astryxdesign/theme-neutral/theme.css';
By the repo’s own account that is the whole setup: the three imports, the provider, and no changes to your build toolchain. The advanced path builds from the TypeScript and StyleX source using @astryxdesign/build, which carries the Babel, PostCSS and Vite plugins, so the bundler emits styles only for components you actually import. Meta puts that path at about a third of the full stylesheet in its own reference app, which is their measurement on their own code rather than a general rule. Each component comes from its own subpath rather than from the package root.
Theming: Behaviour in the System, Appearance in Tokens
Astryx splits responsibility down the middle. Behaviour and accessibility live in the library; appearance lives in a token layer, so a theme config holds colour, typography, radius, spacing and motion, and editing one value restyles every component that reads it without anyone opening component code. Light and dark values sit side by side in the same theme instead of in two parallel files, and a theme can be swapped at runtime or compiled to a static stylesheet. Themes go past CSS variables too: they can override individual components and component parts, and add variants of their own.
Seven ready-made themes ship with the project, and you start from one rather than from nothing: theme list shows what is available, including themes from installed integrations, and theme add <slug> drops the one you pick into your project as source you can edit. That is the design bet in one line. The designer owns a config file, and nobody has to fork or wrap a component to change how it looks.
The Graduated Customization Path
Customization in Astryx escalates through five rungs: use components as shipped, adjust theme tokens, attach class names, layer your own CSS, and finally swizzle a component’s source into your repository. Each rung buys more control and costs more ownership. The first four keep you on the shared upgrade path; the fifth takes that component off it permanently.
| Rung | What you change | What it costs you |
|---|---|---|
| Use as shipped | Nothing | Nothing; upgrades are free |
| Theme tokens | Colour, type, radius, spacing, motion | A config file your team maintains |
| Class names | Per-instance appearance | Cascade-layer discipline |
| Custom CSS | Anything the layer order permits | Selectors that can break on upgrade |
| Swizzle | The component itself | Full maintenance, permanently |
Swizzling is the one-way door. Some internals are simply not exposed by the public API, such as private state, DOM structure or event listeners you cannot reach, and ejecting the source is the only way to them; from that point you maintain the component, not the library. The CLI ejects component source and runs version codemods with astryx swizzle Button and astryx upgrade --apply:
npx @astryxdesign/cli swizzle Button
Use the scoped form for one-off runs: until @astryxdesign/cli is a dependency, npm resolves a bare astryx to an unrelated package. The practical move before adopting Astryx is to check your two or three hardest components against rung five: if the customization you need requires internals, price in owning that source from day one.
Styling Interop: xstyle, className and Tailwind
Astryx components accept both a typed xstyle prop for StyleX overrides and a plain className, so they coexist with Tailwind, CSS Modules or vanilla stylesheets. The same component, three ways:
import * as stylex from '@stylexjs/stylex';
import {Button} from '@astryxdesign/core/Button';
const styles = stylex.create({
save: {alignSelf: 'flex-end', marginBlockStart: 24},
});
// 1. As shipped
<Button label="Save" variant="primary" />;
// 2. Typed StyleX override, compiled at build time
<Button label="Save" variant="primary" xstyle={styles.save} />;
// 3. Plain className, no compiler involved
<Button label="Save" variant="primary" className="ml-auto mt-6" />;
On the pre-compiled path, option three needs no additional toolchain: StyleX is how Astryx authors its styles, not something you have to configure. One condition applies. Astryx loads its stylesheets into cascade layers, @layer reset for the reset and @layer astryx-base for component styles, and layers do not answer to specificity: anything left unlayered, or placed in a layer declared later, wins anyway. So a project that already carries global CSS, an old reset or Tailwind has to set the layer order itself and put every stylesheet in a layer on purpose.
Astryx vs shadcn/ui and Base UI: How Do They Differ?
Meta frames Astryx against two outcomes it names in the launch post: adopt a large company’s design system and you inherit its brand, or assemble copy-pasted components and gain freedom while giving up shared coherence, upstream fixes and an upgrade path, with accessibility landing on your team by default. That is Meta’s argument for its own product, and it is worth checking against what the alternatives say about themselves. shadcn/ui describes itself the other way round: not a library you install, but a way to build your own, handing you the component code to edit directly. Owning the code is the feature, not a side effect, as our look at why teams switch to shadcn/ui covers in more depth. Base UI ships headless React components and hooks with no CSS of their own, so how the result looks is entirely your call.
Read as constraints rather than verdicts: Base UI gives you accessible behaviour and no opinions, shadcn/ui gives you the source and the maintenance that comes with it, and Astryx gives you a themed system you can still eject from per component. Astryx’s fifth rung arrives at the shadcn/ui position by a different route, one component at a time and only when you choose it.
The caveats are straightforward. It is a public beta on 0.x with no stable line, it gates on React 19, and it is a single-vendor project; launch discussion raised governance and long-term-maintenance questions that nothing public settles. Beta churn is not hypothetical: the 0.6.0 release breaks anyone calling useStepperContext directly, stripping the compact-layout fields out of that hook and narrowing StepperContextValue to transition history and step registration. On the other side, the community page describes an official Discord and GitHub issues triaged weekly.
Who Should Try Astryx Now, and Who Should Wait?
Try it now if you are starting a greenfield internal tool or dashboard on React 19, want accessible components without designing them, and have a designer who would rather own tokens than review CSS pull requests. Wait if you are below React 19, if you maintain a public-facing product where a 0.x minor bumping a context shape would cost you a release, or if single-vendor governance is a procurement question you cannot answer yet. A useful middle path is one route of an existing app: pre-compiled stylesheets, explicit @layer order, and a single screen built against components you would otherwise have written yourself.
The thing to evaluate is not the component count. It is which rung of the customization ladder your design requirements force you onto, because that is what you will be paying for a year from now. Pick the two components your product cannot compromise on, run npx @astryxdesign/cli component <Name> against each, and see whether tokens and className get you there before source ejection does.
FAQs
What is the difference between Astryx and StyleX?
StyleX is Meta's build-time CSS-in-JS compiler that turns style objects into atomic, collision-free CSS. Astryx is the design system of React components whose styles are authored with it. Astryx installs @stylexjs/stylex as a peer dependency, but consuming the pre-compiled stylesheets needs no build plugin, no PostCSS and no Babel config. Only source builds pull in the StyleX plugins from @astryxdesign/build.
Does Astryx work with Next.js, Vite or a plain CDN setup?
Yes. The @astryxdesign/core README documents setups for Next.js, Tailwind, Vite and CDN. On the pre-compiled path you import the reset, the component stylesheet and a theme stylesheet, then wrap the app in a theme provider, so no bundler plugin is involved. Building from TypeScript and StyleX source instead requires the Babel, PostCSS or Vite plugins shipped in @astryxdesign/build.
Do I need the Astryx CLI to use the library?
No. The components and pre-compiled CSS work from the installed packages alone, and the CLI is a dev dependency. You need it for theme list and theme add, full component docs, templates, upgrade codemods and swizzling. Running astryx init writes the Astryx component index into AGENTS.md or CLAUDE.md, which only matters when AI agents work in the repository.
Are Astryx chart components ready for production use?
No. @astryxdesign/vega, the Vega wrapper, and @astryxdesign/charts, the d3-based charting library, publish real builds to npm only under the canary dist-tag; their latest tag points at a placeholder release that npm tells you not to install. The experimental @astryxdesign/lab package, where new components land before they graduate into core, is published the same way. Charting therefore sits behind the already beta 0.x core packages and needs its own fallback plan.
Truly understand users experience
See every user interaction, feel every frustration and track all hesitations with OpenReplay — the open-source digital experience platform. It can be self-hosted in minutes, giving you complete control over your customer data.
Star on GitHub12k