Migrate from Tailwind
The csszyx migrate CLI command converts className= (JSX/TSX) or class=
(HTML) attributes to sz= props automatically. It handles static strings, clsx
calls, ternary expressions, and template literals.
Basic Usage
Section titled “Basic Usage”npx csszyx migrate src/ # migrate all JSX/TSX/HTML under src/npx csszyx migrate --dry-run # preview changes without writing filesnpx csszyx migrate --ignore "**/*.test.tsx,**/fixtures/**"npx csszyx migrate --pattern "src/components/**/*.tsx"Migration logs are written to .csszyx/logs/. Add .csszyx/ to .gitignore.
Audit — Discover Unrecognized Classes
Section titled “Audit — Discover Unrecognized Classes”Before migrating, run an audit to see what csszyx cannot automatically convert:
npx csszyx migrate --auditThis scans your codebase and writes .csszyx-todo.json without touching any
source files. Each entry starts as "sz:todo":
{ "btn": "sz:todo", "custom-card": "sz:todo", "animate-spin-slow": "sz:todo"}Resolving the Todo Map
Section titled “Resolving the Todo Map”Edit .csszyx-todo.json to tell csszyx what to do with each class:
| Value | Meaning |
|---|---|
"sz:todo" | Not yet decided — skip, surface in reports |
"sz:keep" | Keep in className, acknowledged as intentional |
"sz:remove" | Drop from output entirely |
{ p: 4, bg: 'blue-500' } | Direct sz object — merged into sz prop |
"p-4 bg-blue-500" | Tailwind string — auto-converted to sz |
null / false | Same as "sz:todo" (backwards compat) |
--resolve-todos — Apply the Resolution Map
Section titled “--resolve-todos — Apply the Resolution Map”npx csszyx migrate --resolve-todos .csszyx-todo.jsonReads .csszyx-todo.json and applies it during migration. Classes mapped to
sz:keep stay in className; sz:remove entries are dropped; sz objects and
Tailwind strings are converted.
--resolve-todos is read-only — it never writes to the todo file. Still-unresolved
sz:todo entries appear in the console and log only.
--inject-todos — Mark Unresolved Classes in Code
Section titled “--inject-todos — Mark Unresolved Classes in Code”npx csszyx migrate --inject-todosInserts {/* @sz-todo: classname1, classname2 */} comments above JSX elements
that still have unrecognized classes — a visual marker so you can grep or skim
the diff to find what needs attention.
When --resolve-todos is active, --inject-todos is automatically enabled for
any still-unresolved classes.
Full Workflow
Section titled “Full Workflow”# 1. Dry run — preview what will changenpx csszyx migrate --dry-run
# 2. Audit — find unrecognized classesnpx csszyx migrate --audit# → writes .csszyx-todo.json
# 3. Edit .csszyx-todo.json# → set "sz:keep", "sz:remove", or direct sz objects for each entry
# 4. Apply with resolution mapnpx csszyx migrate --resolve-todos .csszyx-todo.json
# 5. Re-audit if anything remains unresolvednpx csszyx migrate --auditHTML Files
Section titled “HTML Files”For plain HTML files (no JSX build step), csszyx converts class="..." to
sz="..." attributes. A runtime script is needed at page load to process them —
the migration command can inject it for you.
By default (csszyx migrate public/), the command:
- Converts
class="..."→sz="..."✅ - Injects FOUC prevention CSS into
<head>✅ - Does not inject a runtime script ❌
Injecting the runtime
Section titled “Injecting the runtime”# CDN (default URL: https://cdn.csszyx.com/runtime.js)npx csszyx migrate public/ --inject-runtime cdn
# Local file (default path: csszyx-runtime.js, relative to each HTML file)npx csszyx migrate public/ --inject-runtime local
# Custom CDN URLnpx csszyx migrate public/ --inject-runtime cdn --cdn-url https://my-cdn.com/csszyx.js
# Custom local pathnpx csszyx migrate public/ --inject-runtime local --local-path ./vendor/csszyx-runtime.jsThe runtime script tag is injected before </body>.
FOUC prevention
Section titled “FOUC prevention”Enabled by default. Injects this block before </head>:
<style> /* csszyx: hide [sz] elements until runtime processes them */ [sz] { visibility: hidden; } body.sz-ready [sz] { visibility: visible; }</style>Pass --no-fouc to skip this if you are managing the loading transition yourself.
--braces flag
Section titled “--braces flag”Controls the format of the generated sz attribute value.
Without --braces (default — bare object contents):
<div sz="p: 4, bg: 'blue-500'"></div>With --braces (full object syntax):
<div sz="{ p: 4, bg: 'blue-500' }"></div>Use --braces if your HTML is processed by a template engine that expects
full object literal syntax.
TypeScript Types
Section titled “TypeScript Types”The todo map types are exported for use in custom tooling:
import type { CsszyxTodoEntry, CsszyxTodoMap } from '@csszyx/cli';
// CsszyxTodoEntry = Record<string, unknown> | string | null | false// CsszyxTodoMap = Record<string, CsszyxTodoEntry>