# How to Integrate Astryx with Next.js Using Build Plugins

> Learn to integrate Astryx with Next.js using build plugins. Configure Babel and PostCSS, and use the withAstryx helper for seamless StyleX transpilation. Get started today!

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

---

**To integrate Astryx with Next.js, install the `@astryxdesign/build` package, configure the Babel and PostCSS plugins to compile StyleX with separate class-name prefixes, and use the `withAstryx` helper in `next.config.mjs` to enable source-level transpilation of Astryx packages.**

Astryx is a design system that uses StyleX for type-safe styling. When integrating it with Next.js, you must compile the design system's TypeScript and StyleX source alongside your own code to ensure proper class-name segregation and CSS layer ordering. The `@astryxdesign/build` package provides the necessary Babel, PostCSS, and Next.js utilities to automate this process according to the facebook/astryx repository.

## Why Use Astryx Build Plugins?

The build plugins solve three specific integration challenges when you integrate Astryx with Next.js:

- **Separate CSS Layers** – Library styles receive the `astryx-*` prefix and emit into the `astryx-base` layer, while your application styles use the default `x` prefix and live in the `product` layer. This prevents class-name collisions and ensures theme overrides work predictably.
- **Source Transpilation** – Next.js treats `@astryxdesign/*` packages as source code rather than pre-built bundles, allowing the same Babel and PostCSS pipeline to process both the design system and your application.
- **Simplified Configuration** – The `withAstryx` helper automatically configures `transpilePackages` and Webpack's `resolve.conditionNames` to resolve raw sources under the `source` condition.

## Step 1: Install the Build Dependencies

Install the core build plugin and its peer dependencies. The `@astryxdesign/build` package provides the Babel and PostCSS integration required for the StyleX compilation pipeline.

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

```

This provides the compilers necessary to generate the layered CSS output and handle the separate class-name prefixes.

## Step 2: Configure the Babel Plugin

Create a [`babel.config.js`](https://github.com/facebook/astryx/blob/main/babel.config.js) file in your project root. The `@astryxdesign/build/babel` plugin inspects each file's path to determine whether code belongs to the Astryx library or your application. Library files receive the `astryx` prefix, while application files use the default `x` prefix.

```javascript
// babel.config.js
const path = require('path');

module.exports = {
  presets: ['next/babel'],
  plugins: [
    [
      '@astryxdesign/build/babel',
      {
        dev: process.env.NODE_ENV !== 'production',
        runtimeInjection: false,
        treeshakeCompensation: true,
        enableInlinedConditionalMerge: true,
        aliases: {
          '@astryxdesign/core/*': [path.join(__dirname, 'node_modules/@astryxdesign/core/*')],
          '@astryxdesign/core': [path.join(__dirname, 'node_modules/@astryxdesign/core')],
        },
        unstable_moduleResolution: {type: 'commonJS'},
      },
    ],
  ],
};

```

The `unstable_moduleResolution` setting ensures the plugin correctly resolves StyleX imports from the Astryx packages.

## Step 3: Add the PostCSS Plugin

Create [`postcss.config.js`](https://github.com/facebook/astryx/blob/main/postcss.config.js) to run StyleX a second time, wrapping the generated CSS in `@layer` blocks. The `appDir` parameter tells the plugin where your application code lives so it can distinguish between library and product styles.

```javascript
// postcss.config.js
const path = require('path');

module.exports = {
  plugins: {
    '@astryxdesign/build/postcss': {
      appDir: 'src',
      babelPlugins: [
        [
          '@stylexjs/babel-plugin',
          {
            dev: process.env.NODE_ENV !== 'production',
            runtimeInjection: false,
            treeshakeCompensation: true,
            enableInlinedConditionalMerge: true,
            aliases: {
              '@astryxdesign/core/*': [path.join(__dirname, 'node_modules/@astryxdesign/core/*')],
              '@astryxdesign/core': [path.join(__dirname, 'node_modules/@astryxdesign/core')],
            },
            unstable_moduleResolution: {type: 'commonJS'},
          },
        ],
      ],
    },
  },
};

```

This configuration generates two passes of StyleX output: one for the `astryx-base` layer and one for the `product` layer.

## Step 4: Configure Next.js

You can configure Next.js manually or use the convenience helper from [`packages/build/src/next.js`](https://github.com/facebook/astryx/blob/main/packages/build/src/next.js). The manual approach gives you full control, while the helper streamlines the setup.

### Option A: Manual Configuration

Update `next.config.mjs` to transpile Astryx packages and resolve the `source` condition. This forces Webpack to use the raw TypeScript source files instead of pre-built bundles.

```javascript
// next.config.mjs
/** @type {import('next').NextConfig} */
const nextConfig = {
  transpilePackages: [
    '@astryxdesign/core',
    '@astryxdesign/theme-neutral',
    '@astryxdesign/lab',
  ],
  webpack: config => {
    config.resolve.conditionNames = [
      'source',   // Prioritizes raw source files
      'import',
      'require',
      'default',
    ];
    return config;
  },
};

export default nextConfig;

```

### Option B: Use the withAstryx Helper

Alternatively, import the `withAstryx` function to automatically apply the configuration.

```javascript
// next.config.mjs
import {withAstryx} from '@astryxdesign/build/next';

export default withAstryx({
  // Additional Next.js configuration options
});

```

The helper automatically populates `transpilePackages` and sets the `conditionNames` array to include `source` as the first resolver.

## Step 5: Declare CSS Layers

Create a [`layers.css`](https://github.com/facebook/astryx/blob/main/layers.css) file to define the cascade order. This ensures that Astryx base styles can be overridden by themes and your application code.

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

```

Import this file in your global CSS, followed by the Astryx reset and theme files. The `@stylex` directive triggers the StyleX compilation.

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

@stylex;

```

Placing the layer declarations in a separate file is required because Webpack hoists `@import` statements, ensuring the layers appear in the correct order before any StyleX-generated CSS.

## Summary

- **Install** the `@astryxdesign/build` package along with StyleX Babel dependencies to enable the build pipeline.
- **Configure Babel** to use the Astryx plugin, which applies different `classNamePrefix` values for library (`astryx`) and application (`x`) code.
- **Set up PostCSS** to wrap the compiled CSS in `@layer` blocks, separating `astryx-base` and `product` layers.
- **Configure Next.js** to transpile Astryx packages and resolve the `source` condition, either manually or via the `withAstryx` helper.
- **Declare CSS layers** in a separate file imported before other styles to ensure correct cascade ordering.

## Frequently Asked Questions

### What does the `withAstryx` helper do exactly?

The `withAstryx` helper, defined in [`packages/build/src/next.js`](https://github.com/facebook/astryx/blob/main/packages/build/src/next.js), automatically adds all necessary Astryx packages to the `transpilePackages` array and modifies Webpack's `resolve.conditionNames` to prioritize the `source` condition. This ensures Next.js resolves the raw TypeScript and StyleX source files from `node_modules` rather than consuming pre-compiled JavaScript bundles, enabling your Babel and PostCSS pipelines to process them correctly.

### Why are CSS layers required when using Astryx with Next.js?

CSS layers are required to prevent specificity conflicts between the design system and your application. The Astryx build plugins emit library styles into the `astryx-base` layer and your application styles into the `product` layer. By declaring these layers in a specific order (`astryx-base` before `product`), you ensure that application styles can reliably override design system defaults without resorting to excessive specificity or `!important` declarations.

### Can I customize the Babel configuration while using the Astryx plugin?

Yes, you can extend the Babel configuration passed to the Astryx plugins. Both the Babel and PostCSS plugin configurations accept standard StyleX options, including `aliases`, `unstable_moduleResolution`, and compiler flags like `treeshakeCompensation`. You can also add additional Babel presets or plugins alongside the `@astryxdesign/build/babel` entry in your [`babel.config.js`](https://github.com/facebook/astryx/blob/main/babel.config.js) file.

### Does this integration work with Next.js App Router and Server Components?

Yes, the Astryx build plugins are compatible with the Next.js App Router. The source transpilation and CSS layer generation occur during the build process, producing static CSS files that work with both Server Components and Client Components. Ensure your [`layers.css`](https://github.com/facebook/astryx/blob/main/layers.css) and [`globals.css`](https://github.com/facebook/astryx/blob/main/globals.css) are imported in your root layout file to guarantee the CSS layers are established before any component styles are loaded.