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

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 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])
// 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:

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)

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:

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:

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

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 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.

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 →