# How to Create a Custom Theme Using the Astryx Theme Build CLI Command

> Learn to create a custom Astryx theme using the theme build CLI command. Compile TypeScript into production-ready CSS and JavaScript bundles efficiently.

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

---

**The `astryx theme build` command compiles a TypeScript theme definition into production-ready CSS and JavaScript bundles by processing token maps and generating static assets.**

The Astryx design system provides a dedicated CLI for transforming theme source code into distributable assets. This workflow enables you to define design tokens in TypeScript and export compiled CSS custom properties alongside type-safe JavaScript modules. According to the facebook/astryx source code, the theme compiler located in `packages/cli/api/theme/build/` handles token resolution, light-dark mode tuple expansion, and declaration file generation.

## Setting Up the Theme Package

Start by scaffolding a new theme directory within the monorepo structure.

Create a folder under `packages/themes/` with your theme name (e.g., `ocean`). Inside this directory, initialize the source structure:

```

packages/themes/ocean/
└── src/
    └── oceanTheme.ts

```

If your theme ships custom icons, add an [`icons.tsx`](https://github.com/facebook/astryx/blob/main/icons.tsx) file alongside your entry file and import it into the theme definition.

## Authoring the Theme Definition

The theme entry file must export a theme object created with the `defineTheme` utility from `@astryxdesign/core/theme`.

### Required Structure

The theme object requires two properties:
- **name**: A string identifier for the theme
- **tokens**: A map where keys are CSS custom property names (always prefixed with `--`) and values are either static strings or light-dark tuples (arrays with `[lightValue, darkValue]`)

```typescript
// packages/themes/ocean/src/oceanTheme.ts
import { defineTheme } from '@astryxdesign/core/theme';

export const oceanTheme = defineTheme({
  name: 'ocean',
  tokens: {
    '--color-accent': ['#0077B6', '#48CAE4'],
    '--color-background-surface': ['#F0F8FF', '#0A1628'],
    '--color-text-primary': ['#0A1317', '#FFFFFF'],
    '--radius-container': '16px',
  },
});

```

## Building the Theme

Once your TypeScript source is ready, invoke the build command to generate static assets.

### The Build Command Syntax

Execute from the repository root:

```bash
npx astryx theme build packages/themes/ocean/src/oceanTheme.ts --out dist/ocean

```

The CLI performs the following operations:
1. Loads the source file and extracts the `defineTheme` export
2. Resolves all token values (expanding light-dark tuples into CSS custom properties)
3. Generates a static CSS file containing the design tokens
4. Creates a JavaScript module exporting the built theme object
5. Produces accompanying TypeScript declaration files ([`.d.ts`](https://github.com/facebook/astryx/blob/main/.d.ts))

### CLI Flags and Options

The command supports additional flags for development workflows:

- **`--watch`**: Automatically rebuilds when the source file changes, enabling iterative development
- **`--json`**: Prints a machine-readable receipt to stdout describing the build output, including file counts, token overrides, and output sizes

Example with flags:

```bash
npx astryx theme build packages/themes/ocean/src/oceanTheme.ts \
    --out dist/ocean \
    --watch \
    --json

```

### Output Files Generated

After successful execution, the output directory contains three essential files:

```

dist/ocean/
├── theme.css      // Compiled CSS with custom properties
├── theme.js       // Built Theme object as ES module
└── theme.d.ts     // TypeScript declarations for type safety

```

## Consuming the Built Theme

Integrate the compiled assets into your application by importing both the CSS and the theme object.

### Importing Assets

Load the generated CSS at your application entry point to inject the custom properties into the document:

```typescript
// main.tsx or App.tsx
import './dist/ocean/theme.css';
import { oceanTheme } from './dist/ocean/theme.js';

```

### Runtime Integration with ThemeProvider

Pass the exported theme object to the `ThemeProvider` component (or the `Theme` component) to apply the design system at runtime:

```tsx
import { ThemeProvider } from '@astryxdesign/core';
import { oceanTheme } from './dist/ocean/theme.js';
import './dist/ocean/theme.css';

function App() {
  return (
    <ThemeProvider theme={oceanTheme}>
      <YourApplication />
    </ThemeProvider>
  );
}

```

## Technical Implementation Details

The heavy lifting occurs in the **theme compiler** implementation within `packages/cli/api/theme/build/`. The CLI command itself acts as a thin wrapper that parses arguments, loads the source file using Node.js module resolution, and calls the compiler API to process the theme definition into optimized bundles.

## Summary

- **Scaffold** your theme under `packages/themes/<name>/src/<slug>Theme.ts` with a `defineTheme` export from `@astryxdesign/core/theme`
- **Define tokens** as CSS custom properties (prefixed with `--`) supporting light-dark tuples for automatic dark mode support
- **Build** using `npx astryx theme build <source> --out <dir>` to generate CSS, JS, and TypeScript declaration files
- **Develop** efficiently with `--watch` for automatic rebuilds and `--json` for build analytics
- **Consume** by importing the CSS file and passing the theme object to `ThemeProvider`

## Frequently Asked Questions

### Where does the theme compiler logic live in the repository?

The core compilation logic resides in `packages/cli/api/theme/build/`. This directory contains the implementation that processes the `defineTheme` export, resolves token values, and generates the static CSS and JavaScript bundles consumed by the `astryx theme build` command.

### Can I include custom icons in my Astryx theme?

Yes. Place an [`icons.tsx`](https://github.com/facebook/astryx/blob/main/icons.tsx) file in the same directory as your theme entry file (`src/<slug>Theme.ts`). Import and reference these icons within your theme definition. The build process will bundle them alongside your design tokens when you run the CLI command.

### What is the purpose of the `--json` flag in the theme build command?

The `--json` flag outputs a machine-readable build receipt to stdout. This JSON object contains metadata about the compilation, including the number of files processed, token override counts, and output file sizes, making it suitable for CI/CD pipelines and automated build verification.

### How do I enable automatic rebuilding during theme development?

Add the `--watch` flag to your build command. This monitors the source TypeScript file for changes and automatically triggers recompilation, regenerating the CSS, JavaScript, and declaration files in your output directory without manual intervention.