Plugin Config
CSSzyx is configured by passing options directly to the plugin. There is no
standalone csszyx.config.ts file — all config lives in your bundler config.
Quick Start
Section titled “Quick Start”import csszyx from 'csszyx/vite';import tailwindcss from '@tailwindcss/vite';import react from '@vitejs/plugin-react';import { defineConfig } from 'vite';
export default defineConfig({ plugins: [ ...csszyx({ development: { debug: true, }, production: { mangle: true, injectChecksum: true, }, build: { astBudgetLimit: 50_000, // optional, default 50k cache: true, // optional, enabled by default }, }), tailwindcss(), react(), ],});import type { NextConfig } from 'next';const csszyxWebpack = require('@csszyx/unplugin/webpack').default;
const nextConfig: NextConfig = { webpack(config) { config.plugins.push( csszyxWebpack({ production: { mangle: true, injectChecksum: true }, }), ); return config; },};
export default nextConfig;const csszyxWebpack = require('@csszyx/unplugin/webpack').default;
module.exports = { plugins: [ csszyxWebpack({ production: { mangle: true, injectChecksum: true }, }), ],};TypeScript Types
Section titled “TypeScript Types”import type { PartialCsszyxConfig } from "@csszyx/types";
const csszyxOptions: PartialCsszyxConfig = { exclude: ["src/generated/**"], development: { debug: true }, production: { mangle: true },};Configuration Sections
Section titled “Configuration Sections”development
Section titled “development”Controls development mode behavior.
interface DevelopmentConfig { strictMode: boolean; // Treat warnings as errors debug: boolean; // Enable debug logging}| Option | Default | Description |
|---|---|---|
strictMode | false | Treat all CSSzyx warnings as build errors |
debug | false | Enable verbose debug logging |
For per-element hydration recovery, use the szRecover JSX attribute
on individual elements rather than a global flag — see
SSR & Hydration → Recovery Tokens.
production
Section titled “production”Controls production build behavior.
interface ProductionConfig { mangle: boolean; // Minify class names (z, y, x, ...) mangleVars: boolean; // Opt into dynamic sz CSS variable mangling and hoisting mangleVarHoistMaxDepth: number; // Max cascade depth for mangleVars hoisting mangleGlobalVars?: GlobalVarMangleConfig; // Explicit global token alias tier contentHashing: boolean; // Hash for immutable caching injectChecksum: boolean; // Add hydration checksum to HTML incrementalBuild: boolean; // Enable build caching minify: boolean; // Minify output}interface GlobalVarMangleConfig { enabled: boolean; mode?: 'alias'; tokens?: string[]; autoPrefix?: string; onUnsafeUsage?: 'error'; reserved?: string[]; emitMap?: boolean;}| Option | Default | Description |
|---|---|---|
mangle | true | Replace class names with short encoded symbols |
mangleVars | false | Opt into shorter names and bounded hoisting for dynamic CSS variables generated from runtime sz values. Disabled builds keep existing --_sz-* output. |
mangleVarHoistMaxDepth | 5 | Maximum DOM ancestor distance for component-tier CSS variable hoisting when mangleVars is enabled. |
mangleGlobalVars | undefined | Opt-in alias gate for explicit app-owned global CSS custom properties. Phase H v1 is alias-only and keeps original public variables defined. |
contentHashing | true | Hash CSS output for cache-busting |
injectChecksum | true | Embed SHA-256 checksum in HTML |
incrementalBuild | true | Cache build artifacts for faster rebuilds |
minify | true | Minify emitted CSS and JS |
mangleVars does not define global theme-token aliases. It only rewrites the
dynamic CSS variables csszyx emits for runtime sz values, such as p: pad,
and keeps the feature opt-in while the global token tier remains a separate
design surface.
mangleGlobalVars enables the Phase H global token tier for explicit tokens.
It is default-off, accepts only mode: 'alias', and must not remove original
CSS custom-property names. autoPrefix remains disabled until csszyx can build
the same alias table before source transforms and CSS output validation.
Set emitMap: false only when the standalone .csszyx/global-var-map.json
tooling asset is not needed; csszyx-manifest.json still includes
globalVarAliases when aliases exist.
Controls the build pipeline.
interface BuildConfig { buildId?: string; // Build identifier (auto-generated if omitted) tailwindConfig?: string; // Path to Tailwind config file outputDir?: string; // Output directory cacheDir?: string; // Cache directory cache?: boolean; // Enable per-file transform cache astBudgetLimit?: number; // Max AST nodes per file before the transform skips it (warned) parser?: "babel" | "oxc" | "rust"; // Source parser for JSX/TSX sz transforms scanCss?: string | string[]; // CSS files with @theme blocks to auto-scan}| Option | Default | Description |
|---|---|---|
buildId | Auto | Unique build identifier |
tailwindConfig | 'tailwind.config.js' | Tailwind configuration path |
outputDir | '.csszyx' | Plugin output directory |
cacheDir | '.csszyx/cache' | Incremental build cache |
cache | true | Enable the per-file transform cache. Set to false when debugging parser output or isolating cache-related issues. |
astBudgetLimit | 50000 | Max AST nodes per file before the transform gives up on it — guards against pathologically large generated files. A file past the cap is left unrewritten, contributes no classes to the safelist, and is warned about by every parser engine (the native rust engine included). The safelist prescan runs with a 10× cap by default so real page files keep their CSS; setting this applies your value to both lanes. Raise (e.g. 100_000) when a warning names a legitimate file, or exclude generated files via top-level exclude. |
parser | 'rust' | Source parser for JSX/TSX sz transforms. Default uses the native Rust engine through the matching optional @csszyx/core-* platform package; csszyx fails loudly when the package is missing. Set 'oxc' to opt into the previous JavaScript oxc-parser path on unsupported platforms or for parser-edge-case triage; 'babel' is the final compatibility escape hatch. |
scanCss | undefined | CSS files to scan for @theme blocks. Literal paths and simple globs are supported. |
File Filters
Section titled “File Filters”Use top-level include / exclude to control which source files csszyx parses.
Filters accept literal paths, simple globs, or RegExp patterns. Excludes run before
AST parsing, so large generated files can be skipped without hitting the AST budget.
csszyx({ exclude: ["src/generated/**", /icon-dump\.tsx$/],});Extra Sources (compileSources)
Section titled “Extra Sources (compileSources)”csszyx hard-ignores /packages/ by default (a published library ships
pre-extracted CSS) and pre-scans only the build root. In a monorepo, a
design-system you author — whether under /packages/ or a sibling outside the
build root — is source you want compiled. Opt it in by path:
csszyx({ compileSources: ["packages/vui", "../libs/ui"],});Paths resolve like Vite config paths: relative to the resolved project root
(config.root, default the build cwd); absolute paths pass through. Each entry
(a) exempts that directory from the ignore so its sz/szv is compiled, and
(b) becomes a pre-scan root so its classes are safelisted. Symlinked workspace
packages (pnpm) are matched after realpath resolution (relies on Vite’s default
resolve.preserveSymlinks: false).
node_modules and .next stay ignored unless a listed path points into them. A
/packages/ file with sz that is not under any compileSources directory is
skipped silently (no CSS) — csszyx warns at build end and lists those files. A
path that does not resolve to a directory is reported in a build warning.
A shared lib outside /packages/ (e.g. libs/ui) that lives inside the
build root needs no config — it is compiled and scanned automatically;
compileSources is only needed for /packages/ or for sources outside the
build root.
Content Scope Check (contentScopeCheck)
Section titled “Content Scope Check (contentScopeCheck)”Default true. In a monorepo, Tailwind v4’s automatic content detection climbs to
the workspace root and scans sibling packages + docs (.md/.mdx/.txt are not
ignored), which can generate phantom or broken url() classes and fail the build.
When your Tailwind entry imports tailwindcss without scoping it (no source(none)
/ source(...) / @source not), csszyx warns once at build end with the two-line
fix. Set false to silence that warning when a broad scan is intentional.
csszyx({ contentScopeCheck: false, // silence the unscoped-monorepo warning});See Monorepo & Content Scope for the full fix.
Quiet (quiet)
Section titled “Quiet (quiet)”Default false. Set true to silence all csszyx build warnings — the
skipped-sz, missing-Tailwind-entry, unscoped-content, unresolvable-spread, and
safelist-cap messages. Useful when those warnings are understood and intentional,
or to keep csszyx quiet while you focus on another tool’s output in the build log.
Errors that abort the build (security / crash / build-break guards) still throw —
only warnings are muted.
csszyx({ quiet: true, // silence every csszyx build warning});Theme Auto-Scan (scanCss)
Section titled “Theme Auto-Scan (scanCss)”When set, the plugin parses @theme blocks in your CSS entry point and generates
.csszyx/theme.d.ts — a declaration file that augments the CustomTheme interface
in @csszyx/compiler. This surfaces custom design tokens (colors, spacing, fonts,
radii, shadows) in sz prop IntelliSense without any manual type declarations.
...csszyx({ build: { scanCss: 'src/index.css', // path to CSS with @theme blocks },})@import "tailwindcss";
@theme { --color-brand-500: #6d28d9; --color-brand-600: #5b21b6; --spacing-prose: 65ch; --radius-card: 12px;}After the first build, .csszyx/theme.d.ts is generated. Add it to your
tsconfig.json so TypeScript picks it up:
{ "include": ["src", ".csszyx/theme.d.ts"] }Result: { bg: 'brand-500' } and { maxW: '--spacing-prose' } get full
autocomplete and type-checking.
scanCss accepts a glob or array: ['src/index.css', 'src/tokens.css'].
Theme files are watched in dev mode — hot-reload triggers type regeneration.
The same scan also registers your color, text-size, font-family, and
font-weight tokens into szcn’s merge groups,
so classes built from them dedupe correctly with zero extra wiring. This
matters for semantic token names: with --color-warning and
--color-danger scanned, szcn('text-warning', 'text-danger') keeps only the
later class, while text-warning + text-sm co-exist (color vs size). Without
the scan, szcn cannot tell warning is a color and safely keeps both.
(Shade-shaped names like brand-500 classify by their {name}-{shade} shape
alone and dedupe even unscanned.) Tokens from hand-written CSS outside @theme
can be registered manually with
registerSzcnGroups.
When scanCss is unset, the plugin still discovers @theme blocks on its
own: it walks the project (and any compileSources packages) for CSS files
carrying @theme and feeds their tokens to the szcn groups, so last-wins
merging works with zero config. All @theme option keywords (inline,
static, reference) are recognized. The auto-scan covers runtime merging
only — .csszyx/theme.d.ts type generation still requires an explicit
scanCss, and setting one turns the auto-scan off in favor of exactly the
files you listed.
hydration
Section titled “hydration”Controls SSR hydration verification.
interface HydrationConfig { strict: boolean; // Enable strict checks defaultRecoveryMode?: "csr" | "dev-only"; // Default recovery mode auditLog: boolean; // Log hydration events}| Option | Default | Description |
|---|---|---|
strict | true | Abort on any mismatch (non-configurable in production) |
defaultRecoveryMode | null | No recovery by default |
auditLog | true | Log all hydration events |
performance
Section titled “performance”Controls performance optimizations.
interface PerformanceConfig { parallel: boolean; // Parallel processing during build workers?: number; // Worker thread count (auto-detected) optimizeVariables: boolean; // CSS variable optimization zeroRuntime: boolean; // Static optimization for zero-runtime cases}| Option | Default | Description |
|---|---|---|
parallel | true | Process files in parallel using worker threads |
workers | Auto | Worker count (defaults to CPU cores) |
optimizeVariables | true | Deduplicate CSS custom properties |
zeroRuntime | true | Optimize static sz props to literal strings |