# How to Set Up Vite with @astryxdesign/build for StyleX Source Builds

> Learn to set up Vite with @astryxdesign/build for StyleX source builds. Achieve collision-free theming with separate CSS layers for Astryx and your product code. Maximize injection control.

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

---

**The `@astryxdesign/build` Vite plugin wraps `@stylexjs/unplugin` to compile source-level StyleX with separate CSS layers for the Astryx design system (`astryx` prefix) and your product code (`x` prefix), enabling collision-free theming and injection control.**

Setting up Vite with `@astryxdesign/build` for StyleX source builds lets you compile the Astryx design system directly from TypeScript source alongside your own components. This approach creates a clean separation between library styles and product styles using distinct CSS `@layer` blocks and class-name prefixes. The Vite plugin in `@astryxdesign/build/vite` handles all Babel configuration internally, making integration straightforward.

## Install the Required Packages

Begin by installing the core build plugin and the official StyleX unplugin. According to the [install section in the README](https://github.com/facebook/astryx/blob/main/packages/build/README.md#install), both packages are required for the Vite integration:

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

```

## Configure the Vite Plugin

Import `astryxStylex` from `@astryxdesign/build/vite` and spread its return value into your `plugins` array. The plugin must appear **before** the React plugin so that StyleX's virtual CSS is generated prior to HMR handling, as documented in the [Vite Setup code in the README](https://github.com/facebook/astryx/blob/main/packages/build/README.md#vite-setup).

The `astryxStylex` function accepts a `stylexOptions` object that mirrors the standard StyleX configuration:

```ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { astryxStylex } from '@astryxdesign/build/vite';
import path from 'node:path';

export default defineConfig({
  plugins: [
    ...astryxStylex({
      stylexOptions: {
        dev: process.env.NODE_ENV === 'development',
        runtimeInjection: false,
        treeshakeCompensation: true,
        unstable_moduleResolution: { type: 'commonJS', rootDir: __dirname },
      },
    }),
    react(),
  ],
  resolve: {
    alias: {
      // Resolve the Astryx core source so Vite compiles it from TS
      '@astryxdesign/core': path.resolve(__dirname, 'node_modules/@astryxdesign/core/src'),
    },
  },
  optimizeDeps: {
    // Prevent Vite from pre-bundling the source version of the library
    exclude: ['@astryxdesign/core', '@astryxdesign/theme-neutral'],
  },
});

```

The `resolve.alias` configuration is essential when using source builds—it directs Vite to compile Astryx from its TypeScript source rather than using pre-built artifacts.

## Set Up CSS Layer Ordering

Create a [`layers.css`](https://github.com/facebook/astryx/blob/main/layers.css) file that defines the cascade order for your generated styles. This step, shown in the [layers example in the README](https://github.com/facebook/astryx/blob/main/packages/build/README.md#css-files), ensures predictable style precedence:

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

```

The `astryx-base` and `astyx-theme` layers contain the Astryx design system styles with the `astryx` prefix, while the `product` layer holds your application styles with the default `x` prefix.

## Import Layers and Trigger StyleX Processing

Reference your layers file and Astryx's bundled CSS in your global stylesheet, then add the `@stylex;` directive to trigger StyleX processing:

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

@stylex;

```

The `@stylex;` directive signals the plugin to inject the generated CSS at that location in the output.

## Minimal Working Configuration

For a quick start, the repository's [example Vite app](https://github.com/facebook/astryx/blob/main/apps/example-vite/vite.config.ts) demonstrates a minimal valid configuration:

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

export default defineConfig({
  plugins: [...astryxStylex(), react()],
  resolve: {
    alias: {
      '@astryxdesign/core': path.resolve(__dirname, 'node_modules/@astryxdesign/core/src'),
    },
  },
});

```

This configuration matches lines 4 and 8 of the [source file](https://github.com/facebook/astryx/blob/main/apps/example-vite/vite.config.ts), omitting explicit `stylexOptions` to use sensible defaults.

## How the Plugin Works Internally

The source-level compilation pipeline relies on several key mechanisms implemented in [[`packages/build/src/vite.ts`](https://github.com/facebook/astryx/blob/main/packages/build/src/vite.ts)](https://github.com/facebook/astryx/blob/main/packages/build/src/vite.ts):

- **Prefix separation**: The Astryx library receives the `astryx` class-name prefix; product code keeps the default `x` prefix
- **Layer partitioning**: The plugin intercepts the virtual StyleX CSS endpoint and splits generated rules by file path into separate `@layer` blocks
- **Babel injection**: Required Babel transforms are applied automatically without manual configuration

This architecture prevents class-name collisions between the design system and application code while enabling independent theming and CSS injection strategies.

## What Each Configuration Option Controls

| Option | Purpose |
|--------|---------|
| `dev` | Enables development-mode transforms and debugging |
| `runtimeInjection` | When `false`, emits static CSS files instead of runtime-injected styles |
| `treeshakeCompensation` | Preserves styles for components that may be tree-shaken in production |
| `unstable_moduleResolution` | Resolves StyleX imports relative to the project root |

## Summary

- Install `@astryxdesign/build` and `@stylexjs/unplugin` as dev dependencies
- Add `astryxStylex()` to your Vite plugins array before the React plugin
- Configure `resolve.alias` to point `@astryxdesign/core` at its TypeScript source
- Exclude Astryx packages from `optimizeDeps` to prevent pre-bundling issues
- Define CSS layer order in a dedicated file and import Astryx's reset and theme CSS
- Use `@stylex;` in your global stylesheet to trigger CSS generation

## Frequently Asked Questions

### What is the difference between using @astryxdesign/build and the standard @stylexjs/unplugin directly?

`@astryxdesign/build` wraps `@stylexjs/unplugin` to add automatic layer partitioning and prefix separation specifically for the Astryx design system. Without this wrapper, you would need to manually configure Babel transforms and implement your own logic to separate library styles from product styles. The plugin handles the `astryx` prefix assignment and `@layer` splitting based on file path patterns.

### Why must the Astryx packages be excluded from optimizeDeps?

The `optimizeDeps.exclude` configuration prevents Vite from pre-bundling the source versions of `@astryxdesign/core` and its theme packages. Pre-bundling would transpile these packages to JavaScript and cache them, bypassing the source-level StyleX compilation that enables the prefix and layer separation. Keeping them as excluded allows Vite to process their TypeScript source through the full plugin pipeline on each build.

### Can I customize the class-name prefix or layer names?

The `astryx` prefix and `astryx-base`/`astryx-theme` layer names are hardcoded in the current implementation in [[`packages/build/src/vite.ts`](https://github.com/facebook/astryx/blob/main/packages/build/src/vite.ts)](https://github.com/facebook/astryx/blob/main/packages/build/src/vite.ts). The plugin identifies Astryx source files by their path within `node_modules/@astryxdesign/` and applies these conventions automatically. Customizing them would require modifying the plugin source or forking the repository.

### What happens if I place the react() plugin before astryxStylex()?

Placing `react()` before `astryxStylex()` can cause HMR issues because the React plugin may process file changes before StyleX has generated its virtual CSS. The virtual CSS endpoint must be populated before HMR handlers run to ensure consistent style updates during development. The [Vite Setup documentation](https://github.com/facebook/astryx/blob/main/packages/build/README.md#vite-setup) explicitly recommends the plugin order shown in the configuration examples.