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

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:

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

For Vite projects, also install:

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 to use the Astryx Babel helper:

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

module.exports = babel(__dirname);

The babel() function in 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 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 lines 14-44)

PostCSS Configuration

Create postcss.config.js and point it at the wrapper:

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

module.exports = postcss(__dirname);

The postcss() function in 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:

// 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 (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:

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

Import this from your global 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:

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

This configuration is processed at 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 – Uses @astryxdesign/build/babel
  • 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 Shared Babel and PostCSS configuration generator
packages/build/src/babel.js Babel plugin with dual prefix logic
packages/build/src/vite.ts Vite plugin with layer splitting and dev-mode CSS serving
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 for automatic prefix splitting
  • PostCSS setup – Use postcss(__dirname) in 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 (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) 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).

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →