# How to Configure StyleX Build Plugins for Next.js and Vite with Astryx

> Learn how to configure Astryx StyleX build plugins for Nextjs and Vite. Effortlessly enable compile-time CSS extraction with native integrations for SWC and unplugin.

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

---

**Astryx provides native StyleX integrations via the `@stylexswc/nextjs-plugin` for Next.js SWC pipelines and `@stylexjs/unplugin` for Vite, enabling compile-time CSS extraction without altering core compiler behavior.**

Astryx is a Meta-backed design system that ships first-class StyleX support through dedicated build plugins. This guide demonstrates how to configure these plugins for Next.js and Vite based on the actual implementation in the `facebook/astryx` repository.

## Next.js SWC Integration

Astryx integrates with Next.js through the SWC-based StyleX transform. This approach preserves the native Next.js compiler and `next/font` handling while adding compile-time CSS generation.

### Install the Plugin

Add the community SWC plugin to your Next.js workspace:

```bash
pnpm add -D @stylexswc/nextjs-plugin

```

### Configure next.config.js

Wire the plugin into your Next.js configuration via the `experimental.swcPlugins` array. As shown in [`apps/example-nextjs-stylex/next.config.js`](https://github.com/facebook/astryx/blob/main/apps/example-nextjs-stylex/next.config.js), this keeps the Next.js compiler intact while injecting StyleX processing:

```javascript
const { default: stylexPlugin } = require('@stylexswc/nextjs-plugin');

/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    swcPlugins: [
      [stylexPlugin, { dev: true }],
    ],
  },
};

module.exports = nextConfig;

```

### Runtime Extraction

The SWC plugin performs compile-time CSS extraction and generates a static stylesheet. According to the implementation in [`packages/build/src/vite.ts`](https://github.com/facebook/astryx/blob/main/packages/build/src/vite.ts), it injects a runtime-injection shim only when the `dev` option is set to `true`.

## Vite Unplugin Integration

For Vite projects, Astryx uses `@stylexjs/unplugin` to process StyleX calls within Vite's native pipeline.

### Install the Unplugin

Add the StyleX unplugin to your development dependencies:

```bash
pnpm add -D @stylexjs/unplugin

```

### Configure vite.config.ts

Import the plugin from `@stylexjs/unplugin/vite` and add it to your plugins array. The example in [`apps/example-vite/vite.config.ts`](https://github.com/facebook/astryx/blob/main/apps/example-vite/vite.config.ts) demonstrates this setup:

```typescript
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { stylexPlugin } from '@stylexjs/unplugin/vite';

export default defineConfig({
  plugins: [
    react(),
    stylexPlugin({
      dev: true,
      output: 'dist/stylex',
    }),
  ],
});

```

### Lazy Loading and HMR

As implemented in [`packages/build/src/vite.ts`](https://github.com/facebook/astryx/blob/main/packages/build/src/vite.ts), the plugin lazy-loads the StyleX integration, extracts its shared store via `__stylexGetSharedStore`, and wires up hot-module-replacement for development builds.

## Writing Component Styles

Once configured, consume StyleX in your components using tokens from `@astryxdesign/core`. This component code works identically in both Next.js and Vite environments:

```tsx
import * as stylex from '@stylexjs/stylex';
import { tokens } from '@astryxdesign/core/theme/tokens.stylex';

const styles = stylex.create({
  button: {
    backgroundColor: tokens.brandPrimary,
    padding: `calc(${tokens.spaceMedium} * 2)`,
    ':hover': { opacity: 0.85 },
  },
});

export function FancyButton({ children }) {
  return <button {...stylex.props(styles.button)}>{children}</button>;
}

```

## Configuration Options Comparison

Both plugins support consistent options for controlling development behavior and output:

- **Runtime Injection**: Enable via `dev: true` to inject a development shim; disabled in production builds
- **CSS Output**: Next.js manages output internally (typically `.next/static/css`), while Vite accepts an `output` parameter (e.g., `dist/stylex`)
- **Compatibility**: Next.js plugin works with Next.js 13+ (App Router), while the Vite unplugin supports Vite 8 as used across Astryx

## Summary

- Use `@stylexswc/nextjs-plugin` in Next.js via `experimental.swcPlugins` to preserve SWC compilation
- Use `@stylexjs/unplugin/vite` in Vite projects for rollup-based CSS extraction
- Both plugins dedupe atomic CSS at compile time and support optional runtime injection in development
- Reference `packages/cli/docs/styling.doc.mjs` for authoritative configuration documentation
- Token definitions in [`packages/core/theme/tokens.stylex.ts`](https://github.com/facebook/astryx/blob/main/packages/core/theme/tokens.stylex.ts) provide the design system values consumed by both frameworks

## Frequently Asked Questions

### Does the StyleX plugin break Next.js font optimization?

No. The SWC-based integration preserves `next/font` handling because it operates as a transform within the existing SWC pipeline rather than replacing the compiler. The plugin only processes StyleX-specific calls, leaving other transformations untouched.

### Where does the generated CSS get written in Vite builds?

The Vite plugin emits CSS to the location specified by the `output` option (defaulting to `dist/stylex`). This generated file is served alongside your bundle, and the plugin handles deduplication of atomic classes across your component tree.

### Can I use Astryx design tokens in both Next.js and Vite projects?

Yes. Import tokens from `@astryxdesign/core/theme/tokens.stylex` as shown in [`packages/core/theme/tokens.stylex.ts`](https://github.com/facebook/astryx/blob/main/packages/core/theme/tokens.stylex.ts). These tokens are framework-agnostic StyleX definitions that work identically whether compiled through the Next.js SWC plugin or the Vite unplugin.

### What happens if I disable the `dev` option in production?

When `dev` is set to `false` or omitted, the plugins skip runtime injection and perform only static CSS extraction. This results in zero runtime overhead, with all styles embedded in the generated CSS files rather than being injected by JavaScript.