Panda CSS: build-time, type-safe styles for design systems
š¼ Universal, Type-Safe, CSS-in-JS Framework for Design Systems ā”ļø
At a glance
- What is it?
- Panda CSS (chakra-ui/panda) compiles style objects and style props into atomic CSS at build time, with generated TypeScript types for every token and recipe. It suits teams that want a design system with autocomplete, and it asks for a build step and a codegen artifact in return.
- Who is it for?
- Adopt Panda CSS if you are building a design system in TypeScript and want style objects and recipes checked at compile time; the README's own example is enough to see the ergonomics. Do not adopt it if you need runtime theme switching from arbitrary user input, or if adding a codegen step and an ignored styled-system directory to every contributor's workflow is a dealbreaker.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What Panda CSS solves, and who it is for
The pitch in the README is narrow and specific: write style objects or style props, and have them extracted at build time into modern CSS. The output is plain CSS using cascade layers, CSS variables and atomic utility classes, not a runtime style injector. That distinction is the whole reason to pick it. A design system team that wants tokens, variants and recipes to be checked by the TypeScript compiler gets autocomplete and errors at authoring time instead of discovering a typo in production.
The audience is TypeScript teams maintaining a component library or a shared theme across more than one application. The README lists Stitches-style recipes and variants, high-level design tokens for simultaneous themes, and type-safe styles via codegen. It also states the project works with most JavaScript frameworks, which matters because the styling engine is not tied to React. If your components are plain HTML or another framework, the css function and pattern helpers still apply.
It is a poorer fit for a small marketing site. You would be paying for a compiler, a config file and a generated directory to get what a few hundred lines of hand-written CSS already does.
The build-time pipeline: extractor, parser, generator
The repository layout in the README is the clearest description of the mechanism. A package named extractor contains code for fast AST parsing and scanning. A package named parser contains code for parsing source code. The generator package holds codegen artifacts in js, css and jsx. The core package holds the utility and recipe logic, config reads and merges the panda config, and token-dictionary processes tokens and semantic tokens.
Read together, the data flow is: your source files are scanned as ASTs, the style objects and style props found there are parsed into internal representations, tokens from your config are resolved, and the generator writes out CSS plus TypeScript artifacts. The is-valid-prop package checks whether a prop is a valid CSS prop, which is what makes unknown style props a type error rather than a silently dropped class.
Two consequences follow. First, styles only exist if the scanner sees them, so dynamically constructed class names or props assembled at runtime are outside the model. Second, the generated artifacts are a build product, not source. The entry CSS file must declare the layer order, and the README gives the exact line for that.
Installing Panda CSS and rendering a first styled component
The README calls npm the recommended way to install the latest version, as a dev dependency. The package name is @pandacss/dev.
npm i -D @pandacss/devNext, scaffold the config and PostCSS integration. The -p flag is what the README shows for the init command.
npx panda init -pThat command is documented as scaffolding the panda config and postcss. You should end up with a panda.config.ts at the project root and PostCSS wiring for your bundler.
Your entry CSS file needs the layer order declared before anything else, because Panda's output targets cascade layers. The README gives this line verbatim.
@layer reset, base, tokens, recipes, utilities;Import that entry file once, from your app entry point. The README shows the import as a path to entry.css.
import 'path/to/entry.css'Then start your dev server with your own project's script, for example npm run dev. The README's example component imports css and the stack, vstack and hstack patterns from the styled-system directory that codegen produces.
import { css } from '../styled-system/css'
import { stack, vstack, hstack } from '../styled-system/patterns'
function Example() {
return (
<div>
<div className={hstack({ gap: '30px', color: 'pink.300' })}>Box 1</div>
<div className={css({ fontSize: 'lg', color: 'red.400' })}>Box 2</div>
</div>
)
}What you should see: after the dev server starts, the styled-system directory exists, the imports resolve, and your editor offers completions for token values such as pink.300 and red.400. If the imports do not resolve, codegen has not run or the relative path is wrong for that file's location.
Where the model breaks: runtime values and generated artifacts
The extractor scans source code. That is stated in the package description, and it is the constraint that matters most in practice. A color chosen from a value fetched at runtime, or a class name concatenated from variables the scanner cannot evaluate, has no token to resolve against. Panda's guarantee is a compile-time guarantee, so anything that only exists at runtime falls outside it.
The second cost is the codegen step itself. The README's own example imports from ../styled-system/css, a relative path into a generated directory. That directory has to exist before type checking or the dev server will fail, and it has to be regenerated when config or tokens change. The repository's package.json reflects how much of the project's own workflow depends on codegen: there are scripts named codegen, test:codegen, prepare-studio and build-studio.
A third point is release status. The most recent releases listed for the Vite, webpack and TypeScript plugin packages are all 2.0.0-beta.18, published on 2026-09-17. Beta version numbers on the framework integrations are worth noting if your build pipeline is conservative. The repository itself is not archived and the last push was on 2026-09-18, so work is ongoing, but the integration packages are what they are labelled.
Panda CSS compared with Vanilla Extract and Tailwind CSS
The README's acknowledgement section names its influences directly, which makes the comparison unusually easy to state. Vanilla Extract is credited for inspiring the utilities API. Tailwind CSS is credited for inspiring the JIT compiler and strategy. Stitches is credited for the recipes and variants API. Panda is, by its own account, a synthesis of those three lines of work rather than a departure from them.
The practical difference from Tailwind is where the type safety lives. Tailwind's class strings are strings; Panda's css and pattern calls are typed functions backed by generated declarations, and the is-valid-prop package is what rejects a prop that is not a valid CSS prop. The difference from Vanilla Extract is the authoring surface: Vanilla Extract centres on style files written with its own APIs, while Panda accepts style objects and style props in your component files and extracts them from there. The difference from Stitches is timing. Stitches was a runtime CSS-in-JS library; Panda moves the work to build time and emits static CSS with cascade layers.
If your team already has a working Vanilla Extract or Tailwind setup and no type-safety complaints, the migration cost is real and the README offers no migration path.
Maintenance, licence and the cost of upgrading
The repository is not archived and the last push was on 2026-09-18, so the project is being worked on. The release notes show a coordinated set of 2.0.0-beta.18 packages for Vite, webpack and the TypeScript plugin, all published on 2026-09-17, which suggests the integrations are versioned together.
The repository is a pnpm monorepo with a changesets directory and a release-process.md at the top level, and the root package.json defines a release script that runs changeset publish. That is the upgrade mechanism: versioned changesets published to npm. Upgrading means moving @pandacss/dev and any integration package together, then re-running codegen, because the generated artifacts and the runtime expectations of the packages are produced by the same version.
The licence is MIT, stated in the README as MIT License, copyright 2023 to present Segun Adebayo, with a LICENSE.md at the repository root. MIT is permissive and imposes no copyleft obligation on your application. This is a description of the licence text, not legal advice; if your organisation has specific obligations around attribution in distributed binaries, check LICENSE.md yourself.
Editorial conclusion
Adopt Panda CSS if you are building a design system in TypeScript and want style objects and recipes checked at compile time; the README's own example is enough to see the ergonomics. Do not adopt it if you need runtime theme switching from arbitrary user input, or if adding a codegen step and an ignored styled-system directory to every contributor's workflow is a dealbreaker. Before committing, verify three things on your own project: that npx panda init -p produces a panda.config.ts you can read, that your framework integration (the monorepo ships @pandacss/vite and @pandacss/webpack) matches your bundler, and that the generated import path ../styled-system/css resolves from the directories that import it.
Frequently asked questions
How do I install Panda CSS?
Install the dev package with npm i -D @pandacss/dev, then scaffold the config and PostCSS integration with npx panda init -p. After that, declare the layer order in your entry CSS file and import it from your app entry point.
Does Panda CSS work with frameworks other than React?
The README states that Panda works with most JavaScript frameworks, and the styling is driven by the css function and pattern helpers rather than by React itself. The repository ships separate integration packages such as @pandacss/vite and @pandacss/webpack.
Why is there a styled-system directory in my project?
It is the codegen output. The generator package produces artifacts in js, css and jsx, and the README's example imports css and the pattern helpers from that generated directory. It has to exist before type checking or the dev server will work.
What does the @layer line in the entry CSS do?
The README gives the entry file as @layer reset, base, tokens, recipes, utilities; and describes Panda's output as modern CSS using cascade layers. The line declares the order in which those layers apply, so it needs to be present before the generated styles are used.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/chakra-ui-panda)