Migrating from Master CSS v2 RC
Upgrade a pre-change v2 RC project to named tokens, native declarations, explicit CSS units, and the v2 binding contract.
This guide upgrades six saved RC contracts to language v3 (an internal contract number, not the product version): rc-legacy before named tokens, rc-named before explicit modes and native queries, rc-native before the native-value boundaries, simple-query subset and deterministic source lifecycle, rc-managed before native components and ordered composition, rc-utilities before fixed raw intent and whole-definition replacement, and rc-sizing before entry ownership fixes and preset sizing removal. Check the exact installed RC versions and resolved manifest first; RC releases did not all have identical behavior. Follow stages 2–7 for applicable earlier changes, then the boundary, native-component and utility stages below.
Save the old generated CSS and browser results first. Upgrade related packages, native/Wasm artifacts, manifests, hydration output, and source syntax as one coordinated change. Do not initialize the old and new Master runtimes on the same page.
1. Inventory and save the RC baseline
- Record the installed versions of core, preset, compiler, runtime, server, framework integrations, language tooling, ESLint, and custom bindings.
- Save the resolved RC manifest, its source CSS entries and imports, and the effective
base-unitandroot-sizesettings. A failed settings lookup is not permission to assume defaults. - List custom tokens, inline tokens, modes, namespace fallbacks, managed utilities, variants, and component definitions.
- Find classes in templates, class builders, legacy
@composestatements, safelists, blocklists, test fixtures, and selectors in CSS or JavaScript. Include classes supplied by dependencies and generated content. - Record static, server, runtime, and progressive rendering paths, including hydration manifests, CSS asset URLs, and cached pages.
- Save generated declarations and representative screenshots or computed styles at relevant breakpoints and themes. Include font metrics, background layers, border styles, outlines, and SVG strokes.
Keep the original baseline available throughout migration. Rebuilding an RC manifest with the new engine cannot reconstruct the old overload decisions.
2. Separate names from direct values
A hyphen selects a named token or utility. A colon passes a CSS value. Aliases replace property names; they do not infer another property from a value.
The RC column below is historical reference text, not executable new syntax. brand, md, and similar names refer to tokens from the original project; retain their identities rather than substituting whichever token happens to have the same current value.
| RC reference | New syntax | Generated declaration or semantic change |
|---|---|---|
font:mono | font-mono | font-family:var(--font-family-mono) |
font:bold | font-bold | font-weight:var(--font-weight-bold) |
font:sm | font-sm | font-size:var(--font-size-sm) |
text:sm | text-sm | Retains font size, calculated line height, and letter spacing. |
fg:brand | fg-brand | color:var(--color-brand) |
bg:brand | bg-brand | background-color:var(--color-brand) |
p:md | p-md | padding:var(--spacing-md) |
m:-sm | -m-sm | margin:calc(var(--spacing-sm) * -1) |
fg:red/0.5 | fg-red/0.5 | color:color-mix(in oklab,var(--color-red) 50%,transparent) |
font:16px | font-size:16px | Keeps the old font-size-only intent. |
bg:#fff with color-only intent | background-color:#fff | Keeps other background longhands. New bg:#fff means background:#fff. |
b:2px with width-only intent | border-width:2px | Keeps border style and color. New b:2px means border:2px. |
outline:2px with width-only intent | outline-width:2px | Native outline:2px resets the other outline longhands. |
stroke:2px with width-only intent | stroke-width:2px | Native stroke specifies SVG paint, not stroke width. |
line-clamp:3 with combined truncation intent | clamp-lines:3 | Retains the legacy multi-property truncation utility. line-clamp:3 emits the native declaration. |
p:4x with RC defaults | p:1rem | Converts the old length multiplier; verify the original settings first. |
fg:$color-brand | fg:var(--color-brand) | Explicit native custom-property reference. |
m:sm|md | m:var(--spacing-sm)|var(--spacing-md) | Explicit references in a multi-value declaration. |
grid-cols:3 | Unchanged | Explicit Master parameter utility. |
RC size:20px | width:20px height:20px | The paired sizing family is removed; review cascade order. |
The examples above show variable-backed tokens. A token declared with @theme inline substitutes its declared value instead of a var() reference.
CSS keywords keep native meaning. color:red and fg:red mean the CSS color red; color-red and fg-red select the project's color token. font-family:mono specifies a font named mono and does not resolve --font-family-mono.
There is no implicit token lookup inside a colon value, including functions, fallbacks, and multi-value declarations. For example, use border:1px|solid|var(--color-line-base) and transition:opacity|var(--duration-normal)|var(--easing-standard) when those variables exist.
Preserve selectors and conditions
Keep state suffixes, responsive conditions, important markers, grouping, and | space encoding. Change each affected item inside a group independently.
font:mono:hover@sm!{p:md;fg:brand}:hoverFor this new example, define the project color token explicitly:
@theme { --color-brand: #4f46e5; }font-mono:hover@sm!{p-md;fg-brand}:hoverNamed tokens do not introduce a numeric multiplier scale. p-4 only works if the project defines the corresponding spacing token. Use a real CSS length for a literal.
3. Review resets, names, and cascade order
Native shorthand resets
Choose the property that expresses the original intent. A native shorthand resets omitted longhands, even when its value looks like a single color or width. For example, background:#fff resets background images, positioning, repeat, and sizing; background-color:#fff does not. border:2px also resets border style, whose initial value does not draw a border.
font:16px is not a valid standalone native font shorthand. Use font-size:16px when changing only the size. Use a complete native font value only when its shorthand behavior is intended.
Validate the resulting CSS in a browser. A syntax match is distinct from CSS value validity and from visual equivalence.
Reserved names and ambiguity
Static and enum names keep their existing meanings. bg-cover still emits background-size:cover, even if --color-cover exists; use background-color-cover for that token.
Use full prefixes to resolve collisions. If both --font-family-brand and --font-size-brand exist, font-brand is ambiguous. Choose font-family-brand or font-size-brand. Different utilities cannot resolve ambiguity through registration order.
Resolution uses the longest registered prefix. A missing font-family-sm does not fall back to font-sm. Hyphens inside token names remain part of the token: p-card-body selects --spacing-card-body.
A single utility's explicit namespace fallback order remains meaningful. Negative names apply only to numeric tokens on properties that accept negative values; opacity suffixes apply only to color tokens and use the range 0..1.
Direct values override tokens within the same scope
Both p-md p:8px and p:8px p-md put the token rule before the direct-value rule, so the direct padding wins. HTML class order does not control this result.
Layers, conditions, selector priority, shorthand/longhand tiers, and CSS importance still matter. A padding longhand can override a padding shorthand; an important token can override a normal direct value. Review combinations that relied on RC ordering instead of assuming that every renamed class preserves the previous winner.
4. Replace length x, base-unit, and $name
Master's custom length multiplier is removed. Convert each old length using the original project's effective settings:
rem value = old x value × old base-unit ÷ old root-size| Original settings | RC length | Equivalent CSS length |
|---|---|---|
base-unit:4, root-size:16 | 4x | 1rem |
base-unit:6, root-size:20 | 4x | 1.2rem |
base-unit:6, root-size:20 | -2.5x | -0.75rem |
After converting all affected lengths, remove base-unit from CSS settings and baseUnit from manifest inputs. They are rejected by the new compiler and engine. root-size and rootSize are also removed in the final contract. Keep their saved original values for migration only; query conversion must preserve the old generated result.
Preserve native resolution units. CSS uses x as a resolution unit in image-set() and resolution queries. This is valid new syntax and must retain 1x and 2x:
background-image:image-set(url(a.png)|1x,url(b.png)|2x)background-image: image-set(url(a.png) 1x, url(b.png) 2x);Do not globally replace every numeric x: URLs, strings, resolution descriptors, and custom-property token streams need contextual handling. Inspect arithmetic and nested function values. If the migration tool cannot establish whether a dimension represents a length or resolution, review it manually.
Replace a registered $name reference with var(--name). Preserve any original alpha modifier with an explicit color expression or a named color token. Quoted text containing a dollar sign remains text.
These changes reduce special language rules. They are not a claim that AI generation accuracy has improved; that requires separate model evaluation.
5. Update directives, manifests, and custom hosts
Separate token and raw parameter sources in managed patterns:
@utilities { font-<~font-family> { font-family: --value(); } size-<~container> { width: --value(); height: --value(); } size:<*> { width: --value(); height: --value(); }}prefix-<~namespace> accepts token sources only. Use key:<*> for a complete raw CSS value and a hyphen enum for named options. The former =namespace, typed raw and colon enum forms are historical RC syntax; migrate them through the utility stage below. Full-value --value() substitution remains supported.
A managed definition using a native property name must preserve that property's intent and value. Matching vendor-prefixed declarations may accompany it; changing to a subproperty or adding a separate style effect requires a distinct utility name. For example, migrate the old combined line-clamp definition to clamp-lines.
Regenerate artifacts from their source definitions. Manifest and hydration envelopes remain v1, but the supported field contract changes:
- Token matchers use
{ "type": "token", "prefix": "font-" }with namespace references on their utility; the oldvariablematcher is rejected. - Directive IR has a
tokenpattern distinct fromdynamicraw parameters. - Add
languageVersion: 3to regenerated manifest and hydration data; missing or unsupported language versions are rejected even though their envelope remainsversion: 1. - Replace global mode settings with ordered
modesactivation definitions, and removerootSize,defaultMode,modeTrigger, andsettings.modes. - Remove
baseUnit; update consumers of the generated named-token registry tobuiltinTokenNamespaces. - Preserve rule source priority and semantic sort keys across composition, server rendering, and hydration.
- Update native and Wasm providers together to binding ABI 13. Custom engine adapters must still implement the complete engine interface, including
executionState(). - Rebuild cached generated CSS, server output, progressive payloads, and hydration artifacts with the same package set. Do not mix old rule data with a new runtime.
See the directives contract and rendering modes for the current interfaces. Legacy parsing belongs to the explicitly invoked migration workflow; the production runtime has no old-token fallback.
6. Preview and apply migration proposals
Save the resolved original manifest as master.rc.manifest.json before upgrading. Run the migration command from the project root; --manifest selects that saved file. Missing, unreadable, or invalid configuration stops migration before any writes:
master-css migrate src app.css --from rc-legacy --source-version YOUR_ACTUAL_RC_VERSION --manifest master.rc.manifest.jsonThe default operation proposes changes without writing source files. Inspect the proposal and its diagnostics before applying safe edits:
master-css migrate src app.css --from rc-legacy --source-version YOUR_ACTUAL_RC_VERSION --manifest master.rc.manifest.json --writeAutomatic changes must preserve the token identity, declaration intent, state, and conditions. Length conversion uses the RC settings rather than the new defaults. Equal current numbers do not justify replacing literals with tokens or converting unrelated px values to rem. Remove the retired canonical lint options preferThemeTokens, preferVariableReferences, and preferMultiValueTokens; token migration now uses this explicit command.
Review these cases manually:
- Dynamically concatenated class fragments, including prefixes and values assembled at runtime.
- Names that match multiple token utilities, or custom utility behavior whose equivalence cannot be proven.
- Class combinations whose winner changes under the new ordering.
- CSS selectors,
querySelector, test locators, and generated selector strings that reference escaped old names. - Missing or unreadable RC configuration, unknown source versions, and dimensions with uncertain context.
--write does not override these uncertainties. If any selected file has review diagnostics, the entire selected batch remains unwritten because class and selector dependencies can cross file boundaries. Resolve the diagnostics and preview the batch again. Supply --target-manifest path/to/migrated.json when a migrated project manifest is needed to verify custom definitions. Preserve diagnostics in the upgrade review and resolve them before relying on new build output. Run migration again afterward: already migrated source should produce no additional edits.
Replace removed @compose statements manually with native declarations and selectors. The migration tool leaves these statements unchanged and reports them for review. Update safelists, blocklists, dependency-provided classes, and generated-source producers as well as ordinary markup. Update a generator's source before regenerating its output.
7. Complete the final semantics stage
This stage applies to both RC profiles. If named tokens were already migrated, preview with the named profile and the actual saved version:
master-css migrate src app.css --from rc-named --source-version YOUR_ACTUAL_RC_VERSION --manifest master.rc.manifest.jsonThe version can also come from saved manifest packageVersion metadata. Missing
or unreadable metadata is an error, not permission to use current preset defaults.
The report includes CSS configuration proposals and project-wide review notes.
--write never bypasses those notes or file-level manual-review diagnostics.
Include the original CSS settings source when applying configuration changes; replace app.css in these commands with that entry. A source-only batch cannot silently skip the mode configuration proposal.
Preserve the old query result
The RC column is historical, non-executable text. With the old rootSize: 16,
these examples preserve the old generated dimensions:
| Historical RC reference | Explicit language v2 query | Preserved generated condition |
|---|---|---|
width:10px@>=800 | width:10px@media((width>=50rem)) | @media (width>=50rem) |
display:grid@supports(display:grid) | display:grid@supports((display:grid)) | @supports (display:grid) |
New code authored as @media((width>=800px)) retains 800px; it does not mean
the same thing as the first migrated query under every user font setting.
Breakpoints and container tokens also retain their authored units. If the same
token was used both as a converted RC query and a literal CSS value, split or
review it rather than changing both meanings automatically.
Use complete media, supports, and container syntax, including native parentheses:
grid-cols:2@media((aspect-ratio>=1.5))display:grid@supports((display:grid))grid-cols:2@container(card|(width>=40rem))gap:1rem@container(style(--density:compact))Unknown names no longer become container names. Numeric and feature shorthand inference is gone. Repeated wrappers preserve order and nesting. Review class combinations whose old priority depended on inferred dimensions or root size. An invalid old condition that becomes effective after correction requires a manual behavior decision, not an equivalence claim.
Replace global mode settings
@theme ocean assigns values; @mode ocean assigns activation. Remove
default-mode, mode-trigger, and settings.modes after introducing explicit
branches. For manual light/dark switching with system fallback, define both:
@mode light { @media (prefers-color-scheme: light) { :root:not([data-theme]) { @slot; } } [data-theme="light"] { @slot; }}@mode dark { @media (prefers-color-scheme: dark) { :root:not([data-theme]) { @slot; } } [data-theme="dark"] { @slot; }}@theme { --color-panel: white; }@theme dark { --color-panel: #111827; }:root { color-scheme: light dark; }[data-theme="light"] { color-scheme: light; }[data-theme="dark"] { color-scheme: dark; }Base values come from unqualified @theme; copy the old default-mode values
there when needed. The engine no longer adds color-scheme. The migration
proposal makes old side effects explicit, but overlapping modes, nested themes,
and formerly demand-driven resources still require review. Activation guards
now cover the root element and descendants without adding utility specificity.
For a shadow tree, define a :host(...) branch explicitly. Neither the old class
strategy nor the new mode crosses native shadow boundaries automatically.
Mode redefinition replaces the entire activation definition. Token value blocks still merge by token name. Breakpoints, variants, and modes cannot share names across categories. Mode activation rejects pseudo-elements, declarations, containers, layers, and recursive mode references.
Keep native CSS and choose delivery deliberately
All CSS-producing compiler APIs preserve native CSS by default. Passing classes
no longer enables pruning. To retain intentional RC pruning, set
pruneNativeCSS: true for project-owned sources, or place @prune native; in each
source that should opt in. This directive does not propagate through imports;
@preserve native; excludes its own file. preserveNativeCSS: false still means
explicitly omit native output and is not a pruning option.
Qualified imports cannot contain global definitions. Move @settings, @theme,
@mode, custom variants, and managed definitions to unqualified imports or
reference inputs. Pure native qualified imports and native @variant retain
native conditions. Review imports whose old behavior hoisted definitions.
Official integration defaults are static. Explicitly set the old rendering mode
when preserving a runtime, pre-render, or progressive application. A runtime
flag contradicting its mode is a configuration error. Static and pre-render
must not include runtime engine, Wasm, or runtime manifest assets. Use ordinary
CSS variables for dynamic values in a static app. Rebuild Next manifest imports
as bundler-managed ESM modules; do not depend on private .next/static/media
filenames or manually assembled URLs.
Update diagnostics and custom hosts
Remove output-affecting supportsNativeDeclaration callbacks. Normal generation
preserves even known-invalid native values and reports them separately. Check
matchStatus, cssSyntaxStatus, cssValueStatus, and browserSupport; the former valid or
matched booleans cannot represent these distinctions. Managed declarations are
validated too: grid-cols:2.5 may match but its repeat() count is invalid.
Use validation: 'error' in compiler APIs or master-css generate --strict
for atomic failure on known-invalid values. Unknown capabilities and var()
results remain unverified, rather than being silently removed. Review CSS that
was previously suppressed by a host validator and now reaches the browser.
MCP uses project context by default. A missing entry and an entry that fails to
compile return distinct structured errors; neither silently selects the preset.
Select context: "preset" explicitly for isolated preset queries. Consumers must
read result version 3, full diagnostic and dependency arrays, context metadata,
manifest fingerprint, language version, and binding version. Update editor,
CLI, native, Wasm, server, and hydration consumers together. Ordinary canonical
autofix does not perform version migration or infer pixel/rem equivalence.
8. Verify the coordinated upgrade
- Run the project's build, lint, type-check, and focused application tests with the upgraded package set.
- Compare generated declarations against the saved RC baseline. Explain every difference, including intentionally restored native shorthand semantics and native resolution units.
- Test both orders of token/literal combinations, plus longhands, important values, state selectors, responsive conditions, and themes.
- Check fonts, line heights, letter spacing, backgrounds, borders, outlines, SVG paint and width, and truncation in a browser.
- Compare static, server, runtime, and progressive results wherever the project uses them. Inspect initial hydration and subsequent DOM class updates.
- Check resource retention for tokens referenced by explicit
var(), functions, compositions, modes, and managed animations. - Verify completion, hover, validation, conflict diagnostics, and autofix on representative new classes. Ambiguous names should report explicit alternatives.
- Confirm that official source paths and executable examples no longer rely on RC token syntax,
$name,base-unit, or Master lengthx.
Keep the saved baseline and manual-review decisions with the upgrade change. Remove obsolete RC artifacts only after all rendering paths and important screens validate.
9. RC-native boundary and deterministic-build migration
Select the profile matching the saved installation, not the version you are installing:
| Profile | Saved starting contract |
|---|---|
rc-legacy | Colon tokens, length x, $name, inferred queries and global mode settings |
rc-named | Named tokens and native declaration semantics, before explicit modes and native-query semantics |
rc-native | Explicit @mode, preserved native values and native query suffixes, before the simple-query and source-lifecycle contract |
rc-managed | Before native component authoring and ordered utility composition |
rc-utilities | Native components and ordered composition, before fixed raw intent and whole-definition replacement |
rc-sizing | Four utility definition forms, before entry-level replacement, token ambiguity correction, and removal of built-in paired dimensions |
Every profile requires the actual package version and saved resolved manifest. rc-native does not apply the old mode or root-size conversions.
master-css migrate src --from rc-native --source-version YOUR_SAVED_RC_VERSION --manifest master.rc.manifest.jsonmaster-css migrate src --from rc-native --source-version YOUR_SAVED_RC_VERSION --manifest master.rc.manifest.json --entry src/master.css --writePreview is the default. A batch containing any manual-review item writes nothing. The tool checks source contents again before writing. Use --entry when the project has multiple Master entries; preview still shows the complete proposed CSS.
Keep native values native
The compiler no longer treats --alpha() as a macro. A confirmed old macro call migrates from the following historical RC source:
color: --alpha(var(--color-brand) / .5);color: color-mix(in oklab, var(--color-brand) 50%, transparent);The migration preserves the old oklab space and proportions. A project defining native @function --alpha requires manual review. Ordinary declarations preserve --value() as a native call; only managed patterns substitute it. Native custom-property streams such as --pipe:a|b and --money:$100 keep their spelling. They receive structure checks and an unknown value-grammar status when their type is not known.
Move complex class queries into CSS
Classes retain named conditions, a single media type, one boolean feature/declaration/range, one supports declaration, and a container name with one size or custom-property style query. Functions inside a single value may remain. Repeated simple suffixes retain their wrapper order.
Top-level and, or, not, only, query lists, selector(), compound style queries and literal-pipe syntax belong in CSS. The engine reports MASTER_QUERY_REQUIRES_CSS and includes a CSS template; no quoted-query or new escape syntax is introduced.
@custom-variant language-selector { @supports selector([lang|=en]) { @slot; }}<div class="display:block@language-selector"></div>The migrator proposes names such as migrated-query-<stable-digest> independent of file order. Literal pipes that may have been misdecoded, invalid old queries, generated-selector references, dynamic source and cascade changes require review. Equivalent ranges now share sorting data while retaining original output wrappers; compare overlapping rules against saved CSS and computed styles.
Update source and tool consumers
A source update now replaces its previous class set. Empty content and deletion release rules and resources after their final reference disappears. Custom scanner hosts must use scanSource, removeSource, reconcileSources, registerNativeClasses(owner, names) and removeOwner, and preserve ownership for virtual examples. Candidate collection does not register usage.
Markdown/MDX display text, code fences, inline code and frontmatter no longer generate CSS automatically. Actual JSX/HTML, ESM and expressions still do. Register live examples as parented virtual sources or safelist them. Parsing failures report SOURCE_PARSE_ERROR; they do not fall back to raw text or clear previous successful output.
Use validation: 'report' | 'error' for compiler/stylesheet APIs. The former cssValuePolicy option is rejected. Strict syntax/value errors fail the whole result; unknown capabilities alone do not fail. cssSyntaxStatus, cssValueStatus, matchStatus and browserSupport describe separate checks; an unchecked browser is not-checked.
Upgrade bindings and tools together: ABI 13, source result 2, validator 3, language result 4, diagnostics report 3, MCP result 3. Manifest and hydration envelopes remain v1 with languageVersion: 3; regenerate hydration priorities rather than filling missing fields with RC defaults.
MCP v3 returns { version, metadata, diagnostics, result }. result is either { status: 'success', data } or { status: 'error', error: { code, message } }. Read the published output schema. JSON text equals structuredContent; errors also set isError. Unavailable context/fingerprint data is null and dependencies remain explicit arrays.
Finally verify cold and incremental builds using the same source set: replace, empty, delete and rename a file; change .gitignore; exercise shared classes and live examples; test Next worker publication and custom distDir. Confirm failed builds retain only the last complete development output and fail production. Compare static, SSR, runtime and progressive output, themes, hydration and browser styles before releasing.
Managed defaults and components
Use --from rc-managed for the contract immediately before native component authoring. The existing rc-legacy, rc-named and rc-native profiles include the same final migration stage.
npx @master/css-cli migrate --from rc-managed --source-version <saved-version> --manifest master.rc.manifest.jsonSave the resolved manifest with the original installation before upgrading. Preview is the default; --write applies a batch only after every manual-review item is resolved and every input still matches the analyzed source.
Simple @defaults { prose { ... } } becomes @layer defaults { .prose { ... } }, and @components becomes @layer components with escaped class selectors. Inner declarations and nested rules are preserved. Native styles now ship even when unused and use CSS source order within a layer; native pruning remains opt-in.
Review reported locations for patterns, derived class suffixes, composition references, extraction policy and cascade conflicts. Replace @compose button with native declarations and selectors. Utilities can still be used directly in markup. Write component states and conditions as native CSS. The tool does not silently move components into the utilities layer. Rerunning a completed migration produces no further edits.
Utility intent and whole-definition replacement
Select --from rc-utilities for the saved contract immediately before this change. All five profiles finish with this utility migration stage. Continue to supply the actual installed version and original resolved manifest:
master-css migrate src --from rc-utilities --source-version YOUR_SAVED_RC_VERSION --manifest master.rc.manifest.jsonmaster-css migrate src --from rc-utilities --source-version YOUR_SAVED_RC_VERSION --manifest master.rc.manifest.json --target-manifest master.target.manifest.json --writeConvert definitions while preserving acceptance and intent
The following is historical RC syntax, for comparison only:
@utilities { size:<number|*> { width: --value(); height: --value(); } font-<=font-family> { font-family: --value(); }}@utilities { size:<*> { width: --value(); height: --value(); } font-<~font-family> { font-family: --value(); }}A unique raw-any pattern can be simplified safely. Typed-only patterns, colon enums and overloads require review because :<*> accepts more values. Previously unmatched or ineffective input can start generating effective CSS. Do not silently turn x:<number> into x:<*> without auditing its uses.
text-stroke: now always sets -webkit-text-stroke, including its reset behavior. Use text-stroke-width:2px or text-stroke-color:red to preserve the corresponding old longhand effect. The migrator compares the original emitted property; it does not infer intent from a variable's current color or length. Old var() color guesses require manual review. Named color tokens retain their partial color effect.
Audit replacement, conflicts and composition
A later utility replaces an entire earlier definition, including nested selectors, conditions and dependencies. Empty definitions clear previous output while keeping the name registered. Adjacent static definitions can be merged automatically only when their full source order can be preserved. Overrides across imports/packages, overlapping enums, raw/fixed name collisions and dynamic classes require review.
Enum identity uses the key set, so changing key order is still replacement. Duplicate keys are errors. Token identity preserves the ordered namespace list; =namespace becomes ~namespace. Exact static names precede enum names, and both precede tokens. Unknown but structurally valid static pseudo-classes no longer fall through to a declaration.
All four definition forms accept native declarations and nested rules. Placeholder substitution is limited to parameterized declaration values. Native strings, comments and same-name functions outside managed templates are unchanged.
Compare saved and new declarations, their order, selectors, conditions, variables and animations. Inspect the source of every effective and replaced definition. Verify removal and reinsertion release obsolete resources and that a second migration produces no edits. A batch with any review item writes nothing; changed inputs invalidate a pending write.
Rebuild and validate the complete installation
Upgrade binding ABI 13 and rebuild manifests/hydration with envelope v1 and languageVersion: 3. Older language data is rejected. Custom manifest consumers must remove kind, value matchers and segment dispatch; raw entries use a fixed key matcher. Validator, language, diagnostics and MCP outer versions stay unchanged from the preceding stage.
The default validation: 'report' keeps generated CSS and reports known math grammar errors, including missing operands, invalid separators and known function arity. var(), custom functions and environment-dependent results remain unknown unless a definite independent error exists. validation: 'error' fails the whole build without publishing partial CSS. Neither mode selects a different utility based on a value.
Run builds, lint, declaration comparisons and browser checks across your rendering modes. Verify themes, conditions, hover/focus, hydration and subsequent DOM updates. Retain manual-review decisions and the saved baseline; matching current token numbers is not proof of migration equivalence.
Sizing and resolution
Choose --from rc-sizing when upgrading from four utility definition forms with the built-in size family still present. All six profiles pass through this final migration stage. Keep the actual source package version and saved original manifest:
master-css migrate src --from rc-sizing --source-version YOUR_SAVED_RC_VERSION --manifest master.rc.manifest.jsonmaster-css migrate src --from rc-sizing --source-version YOUR_SAVED_RC_VERSION --manifest master.rc.manifest.json --target-manifest master.target.manifest.json --write| Historical RC input | Current explicit intent |
|---|---|
size:20px | width:20px height:20px |
min-size:20px | min-width:20px min-height:20px |
max-size:20px | max-width:20px max-height:20px |
size-sm | width-sm height-sm, retaining the original token |
Removing the utility does not ban its name: unregistered colon inputs follow native declaration fallback. Do not assume old size: classes are inert; browsers may implement native behavior (the current WebKit test build applies size). Replace the old intent explicitly and compare computed styles. Native @page { size: A4; } remains untouched.
The old min and max aliases retire with min-size and max-size. Logical size-x/size-y aliases and native @page size descriptors are unaffected.
The CLI proposes one grouped replacement, for example {width:20px;height:20px}:hover@sm!, to retain each source occurrence and its suffix. A group is not proof of unchanged sorting. Overlapping width/height rules, selector references, dynamic construction and unproven custom definitions require manual review and block the entire write batch. A custom same-name utility retained in the target manifest is not decomposed. Re-running an applied migration is idempotent.
Removed-utility advice excludes explicitly registered ordinary CSS classes. Custom tooling hosts can pass the project result’s read-only nativeClassNames to createToolingSession or createToolingSessionSync; this suppresses that advice without changing engine generation. The CLI, MCP and language server retain project registrations automatically.
Review token names that used to work only because two definitions happened to produce equal CSS: they now diagnose ambiguity. Give conflicting families distinct prefixes; use suggested full names only when those names actually exist. Overlapping static names and raw keys now replace only their own entry, retaining unrelated aliases. Previously shadowed declarations and resources may therefore change; compare saved output before publishing.
Bare flex still means display:flex. flex:1 and flex:hover select the native property; write display:flex:hover for a state. Completion and hover follow this distinction.
Tooling checks static numeric types as well as math grammar. width:calc(1px + 1s) is invalid, while width:calc(1px * 1px / 1px) has a valid length result. Unknown functions, variables and unresolved percentage contexts remain unknown. Generation preserves declarations; validation: 'error' fails atomically for definite errors.
Next Webpack CSS Modules keep generated theme variables on the compiler's root/mode selectors, delivered through global CSS assets. Remove workarounds that relied on variables copied onto every component: ancestor overrides and nested themes now inherit normally. Turbopack's existing CSS Module directive limitations remain; use native variables from global CSS within Modules.
Rebuild native/Wasm bindings (ABI 13), preset manifests and hydration alongside sources. Manifest/hydration envelope v1 and language version 3 remain unchanged; preserve actual rule/resource/CSSOM verification. Validate light/dark and manual modes, ancestor overrides, route order, HMR and all affected dimensions in browsers before release.