# How to Configure Astryx Build Plugins for Vite, Babel, and PostCSS

> Learn how to configure Astryx build plugins for Vite Babel and PostCSS. Integrate seamlessly into your workflow with StyleX for efficient styling and custom CSS.

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

---

**To configure Astryx build plugins for Vite, Babel, and PostCSS, import `astryxStylex` from `@astryxdesign/build/vite`, add it to your Vite plugins array, and pair it with generated Babel and PostCSS configs that handle the two-pass StyleX compilation with custom class-name prefixes and CSS layer ordering.**

The `facebook/astryx` repository provides a comprehensive build toolchain that integrates StyleX into modern frontend workflows. To configure Astryx build plugins for Vite, Babel, and PostCSS, you need to set up three interconnected entry points that handle class-name generation, CSS layer ordering, and module resolution. Each plugin serves a specific role in the build pipeline, from the Vite orchestration layer to the Babel transformation and PostCSS emission stages.

## Vite Plugin Configuration (`astryxStylex`)

The Vite plugin serves as the primary integration point, located in [`packages/build/src/vite.ts`](https://github.com/facebook/astryx/blob/main/packages/build/src/vite.ts). It orchestrates StyleX compilation, CSS layer ordering, module-resolution aliases, and development server middleware.

### Option Handling and Legacy API Detection

The `astryxStylex` function accepts either modern `AstryxVitePluginOptions` or legacy `AstryxVitePluginLegacyOptions`. It detects legacy configurations by checking for a `stylexOptions` property and automatically forwards these to `astryxStylexLegacy` when needed (lines 111-118 in [`packages/build/src/vite.ts`](https://github.com/facebook/astryx/blob/main/packages/build/src/vite.ts)).

### StyleX Options and Babel Wrapper

By default, the plugin constructs a `stylexOptions` object with development mode enabled, runtime injection disabled, and CommonJS module resolution (lines 21-28). It resolves a companion wrapper script from [`src/babel.js`](https://github.com/facebook/astryx/blob/main/src/babel.js) and injects it as a Vite plugin **before** the unplugin's StyleX instance, adding the `libraryPrefix` option that assigns the `astryx` prefix to library styles (lines 48-66).

### Layer Ordering and Config Aliases

A dedicated Vite plugin inserts a `<style>` tag declaring CSS layers in the correct order: `reset`, `astryx-base`, `astryx-theme`, and `product` (lines 70-79). The config plugin also adds critical aliases for `@astryxdesign/core` to resolve imports to source files, ensuring StyleX can access `tokens.stylex` files (lines 84-96), and excludes `@astryxdesign/*` packages from `optimizeDeps` to prevent pre-bundling that would strip StyleX calls (lines 98-100).

### Dev Server Middleware

During development, the plugin intercepts requests to `/virtual:stylex.css` and implements a split-layer middleware (lines 380-492). This extracts compiled rules from StyleX's shared store, separates them into library and product groups based on the `libraryPattern`, processes each through `processStylexRules`, and serves them wrapped in their respective `@layer` declarations.

## Babel Plugin Configuration (`@astryxdesign/build/babel`)

The Babel plugin, exported from [`packages/build/src/babel.js`](https://github.com/facebook/astryx/blob/main/packages/build/src/babel.js), wraps `@stylexjs/babel-plugin` to inject custom class-name prefixes.

### Config Helper and Wrapper Script

The `babel` function in [`packages/build/src/config.js`](https://github.com/facebook/astryx/blob/main/packages/build/src/config.js) (lines 59-65) returns a standard Babel configuration that loads the wrapper script. This wrapper adds the `classNamePrefix` option, defaulting to `astryx` for library code while keeping the default `x` prefix for product code. The helper `stylexOptions` (lines 38-48) builds base options including dev flags, runtime injection disabled, and treeshake compensation.

## PostCSS Plugin Configuration (`@astryxdesign/build/postcss`)

The PostCSS plugin, defined in [`packages/build/src/index.js`](https://github.com/facebook/astryx/blob/main/packages/build/src/index.js), performs the two-pass StyleX compilation and emits CSS into distinct layers.

### Two-Pass Compilation and CSS Layer Emission

The plugin collects source files based on `include` globs (lines 28-38), then runs two Babel transforms: one with the `astryx` library prefix and one with the default `x` prefix (lines 98-108). It aggregates StyleX metadata into separate maps for library and product styles (lines 61-84), calls `processStylexRules` to generate CSS strings, and wraps each in `@layer` blocks (`astryx-base` and `product`) before replacing the `@stylex` at-rule in the source (lines 14-22, 33-36).

The `postcss` generator in [`packages/build/src/config.js`](https://github.com/facebook/astryx/blob/main/packages/build/src/config.js) (lines 75-88) creates the configuration that loads this plugin along with `autoprefixer`, and supports an `extraInclude` option for additional file globs.

## Complete Configuration Example

To wire everything together in a Vite project:

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

export default defineConfig({
  plugins: [...astryxStylex(), react()],
});

```

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

module.exports = babel(__dirname);

```

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

module.exports = postcss(__dirname);

```

This setup gives you a complete pipeline where Vite handles the build orchestration, Babel transforms the JavaScript with proper class-name prefixes, and PostCSS emits the final CSS into ordered layers.

## Customizing Plugin Options

You can customize the configuration through several options:

**Layer names** – Override the default `astryx-base` and `product` layer names via the `layers` option:

```typescript
plugins: [
  ...astryxStylex({layers: {library: 'my-lib', product: 'my-app'}}),
  react(),
]

```

**Library prefix** – Change the library class-name prefix to avoid clashes:

```typescript
plugins: [...astryxStylex({stylexPrefix: 'myPrefix'}), react()]

```

**LightningCSS targets** – Pass `lightningcssTargets` for optimization (see `LIGHTNINGCSS_TARGETS` constants in [`vite.ts`](https://github.com/facebook/astryx/blob/main/vite.ts)).

**PostCSS extra includes** – Add additional file globs via the `extraInclude` option in the PostCSS configuration, useful for monorepo setups.

All options are fully typed in `AstryxVitePluginOptions` (lines 40-87 in [`packages/build/src/vite.ts`](https://github.com/facebook/astryx/blob/main/packages/build/src/vite.ts)).

## Summary

- The `astryxStylex` Vite plugin in [`packages/build/src/vite.ts`](https://github.com/facebook/astryx/blob/main/packages/build/src/vite.ts) orchestrates StyleX compilation, CSS layer ordering, and dev-server middleware.
- The Babel plugin in [`packages/build/src/babel.js`](https://github.com/facebook/astryx/blob/main/packages/build/src/babel.js) wraps `@stylexjs/babel-plugin` to inject the `astryx` class-name prefix for library code while keeping `x` for product code.
- The PostCSS plugin in [`packages/build/src/index.js`](https://github.com/facebook/astryx/blob/main/packages/build/src/index.js) runs two-pass compilation and emits CSS into `astryx-base` and `product` layers.
- Use `optimizeDeps.exclude` to prevent Vite from pre-bundling `@astryxdesign/*` packages, which would strip StyleX calls and cause runtime errors.
- The dev server serves virtual CSS at `/virtual:stylex.css` with automatic layer splitting based on the `libraryPattern` configuration.

## Frequently Asked Questions

### How do I configure Astryx build plugins for Vite, Babel, and PostCSS in an existing project?

Import `astryxStylex` from `@astryxdesign/build/vite` and spread it into your Vite plugins array. Then create [`babel.config.js`](https://github.com/facebook/astryx/blob/main/babel.config.js) and [`postcss.config.js`](https://github.com/facebook/astryx/blob/main/postcss.config.js) files that use the `babel` and `postcss` helpers from `@astryxdesign/build`. This establishes the three-way integration that handles StyleX compilation, class-name prefixing, and CSS layer emission without manual CSS file management.

### Why does the Vite plugin exclude `@astryxdesign/*` packages from dependency optimization?

Vite's dependency pre-bundling would strip StyleX calls from the library code, causing runtime errors. The plugin automatically adds `optimizeDeps.exclude` patterns for all `@astryxdesign/*` packages (lines 98-100 in [`packages/build/src/vite.ts`](https://github.com/facebook/astryx/blob/main/packages/build/src/vite.ts)) to preserve the StyleX metadata needed for the Babel and PostCSS transformations.

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

The `astryx` prefix is applied to library code (design system components) while the `x` prefix is used for product code (application-specific styles). This separation allows the PostCSS plugin in [`packages/build/src/index.js`](https://github.com/facebook/astryx/blob/main/packages/build/src/index.js) to split styles into distinct CSS layers (`astryx-base` vs `product`) and prevents class-name collisions between library and application code during the two-pass compilation.

### How does the dev server handle CSS layer splitting?

When the dev server receives a request for `/virtual:stylex.css`, the middleware in [`packages/build/src/vite.ts`](https://github.com/facebook/astryx/blob/main/packages/build/src/vite.ts) (lines 380-492) extracts rules from StyleX's shared store, splits them by origin using the `libraryPattern`, processes each group through `processStylexRules`, and wraps them in the appropriate `@layer` declarations before serving the response. This ensures library styles are contained in `astryx-base` layers while product styles remain in `product` layers during development.