# How to Configure Astryx Build: Babel, PostCSS, and Vite Setup Guide

> Configure Astryx build using Babel, PostCSS, and Vite. Learn automatic CSS layer splitting and dual class-name prefixes for your library and product code with @astryxdesign/build.

- Repository: [Meta/astryx](https://github.com/facebook/astryx)
- Tags: how-to-guide
- Published: 2026-08-03

---

**Use `@astryxdesign/build` to configure Babel, PostCSS, or Vite with automatic CSS layer splitting and dual class-name prefixes for library and product code.**

Astryx ships components as source code that must be compiled with StyleX. The `@astryxdesign/build` package provides three build integrations that handle the complexity automatically. According to the **facebook/astryx** source code, the package splits class-name prefixes between library files (`astryx`) and product code (`x`), places each group in dedicated CSS layers, and resolves `@astryxdesign/*` imports to source files rather than the compiled `dist` bundle.

## Installation Requirements

Install the core build package plus StyleX dependencies:

```bash
npm install -D @astryxdesign/build @stylexjs/babel-plugin @babel/core

```

For **Vite projects**, also install:

```bash
npm install -D @stylexjs/unplugin

```

- `@astryxdesign/build` – the wrapper that configures StyleX for Astryx
- `@stylexjs/babel-plugin` – compiles StyleX; the wrapper adds per-layer prefix logic
- `@babel/core` – runtime required for the Babel plugin
- `@stylexjs/unplugin` – Vite-compatible unplugin used by the Vite wrapper

## Babel Configuration

Create or update **[`babel.config.js`](https://github.com/facebook/astryx/blob/main/babel.config.js)** to use the Astryx Babel helper:

```js
// babel.config.js
const {babel} = require('@astryxdesign/build');

module.exports = babel(__dirname);

```

The `babel()` function in [`packages/build/src/config.js`](https://github.com/facebook/astryx/blob/main/packages/build/src/config.js) (lines 59-78) generates a configuration that:

1. Adds the Next.js preset with `allowDeclareFields` for TypeScript `declare` class fields
2. Loads the Astryx Babel plugin from [`packages/build/src/babel.js`](https://github.com/facebook/astryx/blob/main/packages/build/src/babel.js) with options from `stylexOptions()` (lines 38-49)
3. Applies per-file prefix detection—library files receive the `astryx` prefix, product files receive `x` (see [`babel.js`](https://github.com/facebook/astryx/blob/main/babel.js) lines 14-44)

## PostCSS Configuration

Create **[`postcss.config.js`](https://github.com/facebook/astryx/blob/main/postcss.config.js)** and point it at the wrapper:

```js
// postcss.config.js
const {postcss} = require('@astryxdesign/build');

module.exports = postcss(__dirname);

```

The `postcss()` function in [`packages/build/src/config.js`](https://github.com/facebook/astryx/blob/main/packages/build/src/config.js) (lines 81-102) returns a PostCSS configuration that:

- Instantiates the Astryx StyleX Babel plugin with consistent options
- Adds `autoprefixer` for vendor prefixes
- Wraps generated CSS in `@layer` blocks—library styles go to `astryx-base`, product styles to `product`

## Vite Configuration

For Vite-powered projects (including Storybook), add the Astryx plugin to **[`vite.config.ts`](https://github.com/facebook/astryx/blob/main/vite.config.ts)**:

```ts
// vite.config.ts
import {defineConfig} from 'vite';
import react from '@vitejs/plugin-react';
import {astryxStylex} from '@astryxdesign/build/vite';

export default defineConfig({
  plugins: [
    // Spread the Astryx StyleX plugins, then any other plugins
    ...astryxStylex(),
    react(),
  ],
  resolve: {
    alias: {
      // Resolve core source to enable StyleX compilation
      '@astryxdesign/core': require.resolve('@astryxdesign/core/src'),
    },
  },
  optimizeDeps: {
    // Prevent pre-bundling that would strip StyleX calls
    exclude: ['@astryxdesign/core'],
  },
});

```

The `astryxStylex()` function in [`packages/build/src/vite.ts`](https://github.com/facebook/astryx/blob/main/packages/build/src/vite.ts) (lines 11-30) creates four specialized plugins:

- **`configPlugin`** – Injects `resolve.alias` and `optimizeDeps.exclude` (lines 83-121)
- **`layerOrderPlugin`** – Inserts a `<style>` tag declaring CSS layer order (lines 69-81)
- **`basePlugin`** – Wraps `@stylexjs/unplugin` with custom Babel options for correct prefix enforcement (lines 52-66)
- **`splitLayerPlugin`** – In dev mode, intercepts `/virtual:stylex.css`, partitions rules by file path (library vs. product), and serves them in respective `@layer` blocks (lines 124-200)

The legacy API `astryxStylexLegacy` remains available for older Storybook setups (lines 303-328).

## CSS Layer Declaration

Create an explicit layer order file to guarantee cascade priority:

```css
/* src/app/layers.css */
@layer reset, astryx-base, astryx-theme, product;

```

Import this from your global CSS:

```css
/* src/app/globals.css */
@import './layers.css';
@import '@astryxdesign/core/reset.css';
@import '@astryxdesign/theme-neutral/theme.css';

@stylex;

```

Webpack (used by Next.js) hoists `@import` content above inline CSS, so a separate layer definition file ensures the order is respected.

## Advanced: Browser Targets with LightningCSS

To lower `light-dark()` calls for specific browsers, pass `lightningcssTargets` to `astryxStylex`:

```ts
astryxStylex({
  lightningcssTargets: {
    chrome: 123 << 16,
    firefox: 120 << 16,
    safari: (17 << 16) | (5 << 8),
  },
});

```

This configuration is processed at [`packages/build/src/vite.ts`](https://github.com/facebook/astryx/blob/main/packages/build/src/vite.ts) lines 71-75.

## Complete Next.js Source Build Example

The repository includes a working implementation at **`apps/example-nextjs-source`**. The essential files demonstrate the full pipeline:

- **[`babel.config.js`](https://github.com/facebook/astryx/blob/main/babel.config.js)** – Uses `@astryxdesign/build/babel`
- **[`postcss.config.js`](https://github.com/facebook/astryx/blob/main/postcss.config.js)** – Uses `@astryxdesign/build/postcss`
- **`next.config.mjs`** – Configures `transpilePackages` and `conditionNames` (see README lines 99-108)

## Key Implementation Files

| File | Purpose |
|------|---------|
| [`packages/build/src/config.js`](https://github.com/facebook/astryx/blob/main/packages/build/src/config.js) | Shared Babel and PostCSS configuration generator |
| [`packages/build/src/babel.js`](https://github.com/facebook/astryx/blob/main/packages/build/src/babel.js) | Babel plugin with dual prefix logic |
| [`packages/build/src/vite.ts`](https://github.com/facebook/astryx/blob/main/packages/build/src/vite.ts) | Vite plugin with layer splitting and dev-mode CSS serving |
| [`packages/build/README.md`](https://github.com/facebook/astryx/blob/main/packages/build/README.md) | Author-level documentation and usage patterns |

## Summary

- **Install** `@astryxdesign/build` plus StyleX peer dependencies for your target environment
- **Babel setup** – Use `babel(__dirname)` in [`babel.config.js`](https://github.com/facebook/astryx/blob/main/babel.config.js) for automatic prefix splitting
- **PostCSS setup** – Use `postcss(__dirname)` in [`postcss.config.js`](https://github.com/facebook/astryx/blob/main/postcss.config.js) for layer-wrapped CSS output
- **Vite setup** – Spread `...astryxStylex()` in plugins array and configure source resolution aliases
- **CSS layers** – Declare explicit layer order in a separate file due to Webpack hoisting behavior
- **Browser targeting** – Pass `lightningcssTargets` for advanced transpilation needs

## Frequently Asked Questions

### What is the difference between the `astryx` and `x` class-name prefixes?

The `astryx` prefix applies to library files within `@astryxdesign/*` packages, while the `x` prefix applies to product code in your application. This separation, implemented in [`packages/build/src/babel.js`](https://github.com/facebook/astryx/blob/main/packages/build/src/babel.js) (lines 14-44), prevents style collisions and enables distinct CSS layer assignment.

### Why does Astryx require building from source instead of using pre-compiled dist files?

Astryx components ship as source code to allow StyleX compilation within your project's build pipeline. This ensures consistent optimization, proper CSS layer integration, and elimination of duplicate StyleX runtime code that would occur with pre-compiled bundles.

### How does Vite development mode handle CSS layers differently than production?

In development, `splitLayerPlugin` (lines 124-200 in [`vite.ts`](https://github.com/facebook/astryx/blob/main/vite.ts)) intercepts the virtual `/virtual:stylex.css` request, partitions collected style rules based on file path analysis, and dynamically serves them wrapped in their respective `@layer` blocks. Production builds generate static CSS with layers baked in.

### Can I use Astryx with Storybook?

Yes—use the `astryxStylex()` Vite plugin for Storybook 7+ with Vite, or `astryxStylexLegacy()` for older Storybook setups. Both APIs are exported from `@astryxdesign/build/vite` and handle the necessary configuration for StyleX compilation within Storybook's build pipeline (see lines 303-328 in [`vite.ts`](https://github.com/facebook/astryx/blob/main/vite.ts)).