SuperAPI AI Directory

panda-css-migrate

Frontend & websites

View repository

Updated 10-15 20:11

About this skill

Panda CSS v1 → v2

v2 keeps the authoring API and rewrites the compiler in Rust. Your panda.config.ts carries over. What breaks is mostly config plumbing, a few CLI flags, and packages that no longer exist.

The full guide is Upgrading to v2. This skill is the ordered path through it. Read the guide for anything below that needs detail.

Before you start

Check the project can even run v2:

  • ESM only. No CommonJS build. The project needs "type": "module", .mjs files, or an ESM-aware bundler. require('@pandacss/dev') will not work.
  • Node 22 or newer. Published packages declare "engines": { "node": ">=22" }.

If either fails, fix that first. Nothing else matters until the config loads.

Upgrade checklist

Work in order. Run panda build after each group; failures compound if you batch them.

1. Move every @pandacss/* package to v2 together.

pnpm add -D @pandacss/dev@latest
pnpm add -D @pandacss/postcss@latest   # or @pandacss/vite, @pandacss/webpack, @pandacss/rollup

Never mix a v1 package with a v2 one. All packages share one version.

2. Drop imports of packages that no longer exist. Their work moved into @pandacss/compiler: @pandacss/core, @pandacss/extractor, @pandacss/generator, @pandacss/node, @pandacss/parser, @pandacss/token-dictionary, @pandacss/is-valid-prop, @pandacss/logger, @pandacss/reporter, and @pandacss/studio. If the project only uses @pandacss/dev plus a bundler plugin, there's nothing to do.

3. Add presets explicitly. v2 does not auto-inject them. A config without them gets a bare system: no bg or color utilities, no spacing or font scales, no _hover.

export default defineConfig({
  presets: ['@pandacss/preset-base', '@pandacss/preset-panda'],
})

This is the most common "everything is broken after upgrading" cause.

4. Move hooks onto plugins.

// ❌ v1
hooks: { 'parser:before': handler }

// ✅ v2
plugins: [{ name: 'local', hooks: { 'parser:before': { filter: { id: '**/*.{jsx,tsx}' }, handler } } }]

Supported: config:resolved, preset:resolved, parser:before, codegen:prepare, codegen:done, cssgen:done.

Gone: context:created, parser:after, config:change, tokens:created, utility:created, and parser:before.configure(...). cssgen:done is now observe-only, so it can't rewrite the CSS string.

If you used cssgen:done to strip unused tokens or keyframes, use optimize instead:

optimize: {
  removeUnusedTokens: true,
  removeUnusedKeyframes: true,
  smartCompoundVariants: true,
}

5. Split createStyleContext. It's gone from <outdir>/jsx.

  • Config recipe (cva) → createRecipeContext → { withContext }
  • Slot recipe (sva) → createSlotRecipeContext → { withRootProvider, withProvider, withContext }

6. Convert template literal styles to objects. The syntax option, the --syntax init flag, and tagged-template styling are all removed.

// ❌ v1
const Button = styled.button`
  padding: 10px 15px;
`

// ✅ v2
const Button = styled('button', { base: { padding: '10px 15px' } })

Run panda codegen --clean afterwards so the old runtime is regenerated.

7. Replace globalPositionTry. Use theme.positionTry plus the positionTry() factory.

// ✅ v2
theme: {
  positionTry: {
    bottom: {
      top: 'anchor(bottom)'
    }
  }
}
css({ positionTryFallbacks: positionTry('bottom') })

8. Fix scrollbarWidth. It takes auto | thin | none now, not a sizes token. scrollbarWidth: '4' was always invalid CSS. A single color token on scrollbarColor moves to scrollbarThumb.

9. Update CLI usage.

  • panda inspect, panda validate, panda info → panda doctor (add --json for scripts)
  • panda ship → panda lib, and consumers set designSystem in config
  • panda mcp / panda init-mcp → npx -y @pandacss/mcp
  • --cpu-prof → --profile (writes .panda/trace.json and .panda/timings.json)
  • --silent / --quiet / --verbose → --log-level silent|error|warn|info|debug
  • Shared flags are kebab-case: --max-warnings, --watch-debounce, --trace-output, --trace-file

10. Rewire design systems. If the project shipped or consumed a library with panda ship:

// consumer config
export default defineConfig({ designSystem: '@acme/design-system' })

Never put build info in include. Import styles from your local outdir after running panda build.

11. Run the build and read the diagnostics. panda build, then panda doctor. A panda debug dump under <outdir>/debug shows exactly what the new engine extracted if something looks wrong.

If the CSS changed

v2 aims for v1 parity. These differences are deliberate, so check them before filing a bug:

  • Border and shorthand overrides. Atomic rules sort by property breadth, not source order. An all-sides shorthand now beats a per-side override. Use the longhand when the override must win: borderInlineEndWidth: '0', not borderInlineEnd: '0'.
  • Compound variants emit eagerly as named classes in @layer recipes.compound_variants. Set optimize.smartCompoundVariants: true to emit only the combinations you use.
  • No universal variable reset. v1 seeded --translate-x, --blur and friends on every element. v2 registers them with @property. If you target engines without @property support, set optimize.propertyFallback: true.
  • Breakpoints use range syntax, @media (width >= 48rem). px and em normalize to rem.
  • Prefixed declarations come first (-webkit-mask-image before mask-image).
  • Unused @property registrations are dropped. If the only thing reading a registered variable is CSS that Panda never scans, declare it in globalCss too.
  • Adjacent rules with identical declarations merge, and rules sharing a @media or @supports wrapper are grouped.

Class names changed in a few places (typography shorthands, for instance). Don't assert on generated class names.

Things that moved, not broke

If the upgrade surfaces one of these, it isn't a regression you introduced:

  • The Astro-based Studio is gone. A CLI-generated replacement is planned.
  • Some community presets (preset-atlaskit, preset-open-props) and standalone plugins aren't ported. Use the first-party @pandacss/preset-typography instead of the community typography preset. Its default size is md, not base.
  • If the build misbehaves under @pandacss/postcss, try the Vite plugin or plain panda build to isolate it before filing a bug.

It's working if

  • panda build completes with no diagnostics on a config you didn't have to rewrite.
  • presets is set explicitly, and utilities like bg and conditions like _hover resolve again.
  • Nothing imports @pandacss/core, @pandacss/node, or the other folded packages.
  • No hooks key sits at the config root, and no call to createStyleContext survives.
  • The CSS diff against v1 contains only the deliberate differences listed above.

See also

  • The full guide: Upgrading to v2.
  • Writing styles once the upgrade is done: call the Skill tool with "panda-css".
  • Tokens and recipe architecture: call the Skill tool with "panda-css-theming".