Plumeria 21.2
Plumeria v21.2 lets a package share Plumeria definitions. An app reads the css.createStatic values, styles and keyframes a package exports as it reads its own modules, and @plumeria/wind, the Tailwind CSS design tokens as a package, is the first one built this way.
1. Definitions from a package
Until now the compiler read definitions only from the app's own files. A package opts in by pointing a plumeria condition at its TypeScript source:
{
"name": "@acme/tokens",
"exports": {
".": {
"plumeria": "./src/index.ts",
"types": "./src/index.ts"
}
}
}import * as css from '@plumeria/core';
export const brand = css.createStatic({
primary: '#0b5fff',
});An app that lists the package in its dependencies reads it like a local module:
import * as css from '@plumeria/core';
import { brand } from '@acme/tokens';
const styles = css.create({
button: {
backgroundColor: brand.primary,
},
});The compiler follows the plumeria condition, including subpath and pattern exports such as @acme/tokens/colors, and packages linked from a pnpm store. dependencies, devDependencies, peerDependencies and optionalDependencies all count. A package without the condition is not read.
An import whose names are all compiled away is now removed from the output, so the bundler never resolves @acme/tokens here. A package that exports only definitions can ship its source alone. One that also exports runtime code keeps a default condition for it, and an import still read at runtime, rendered as a component or re-exported stays in place.
2. @plumeria/wind
@plumeria/wind provides the Tailwind CSS v4.3.3 design tokens as css.createStatic values: the color palettes, spacing, type scale, font weights, radius, shadows, easing, breakpoints and animations.
npm i -D @plumeria/windimport * as css from '@plumeria/core';
import { blue, radius, slate, spacing, text } from '@plumeria/wind';
const styles = css.create({
button: {
paddingInline: spacing[4],
fontSize: text.sm,
color: slate[50],
backgroundColor: blue[600],
borderRadius: radius.md,
},
});It is built the way section 1 describes: its package.json points a plumeria condition at src/index.ts, and there is no build output. Every value is compiled into the styles that read it and the import is removed, so nothing from the package reaches the bundle. It generates no utility classes. The full list is in @plumeria/wind.
3. Namespace imports
21.0 made a namespace read of a definition a compile error. A read by name now compiles as a named import does:
import * as css from '@plumeria/core';
import * as tokens from './tokens';
const styles = css.create({
link: { color: tokens.blue[500] },
});tokens.blue is read as import { blue }, and the namespace import is removed when nothing else uses it. A string key, destructuring, a rest element or passing tokens as a whole still stops the build and asks for a named import.
4. Lint
no-combinator checks only the css.createStatic values that start with : or [, the ones that become a selector when used as a key. A value with spaces, such as a shadow or a font stack, is no longer reported. no-unknown-css-properties accepts fit-tolerance, min-size and max-size.
Upgrading
A module imported only for its definitions is no longer loaded through that import. If it also runs code on import, such as importing a global stylesheet, import it for its side effects as well:
import './tokens';Release notes
21.2.0 (Oct 30, 2026)
- Feat: a package can share its Plumeria definitions as source: when its
exportspoint aplumeriacondition at its TypeScript files, as in"plumeria": "./src/index.ts", an app that lists it in its dependencies reads the definitions it exports, such ascss.createStaticvalues,css.createstyles andcss.keyframesnames, as it reads a local module, including subpath and pattern exports and packages linked from a pnpm store - Feat:
@plumeria/windprovides the Tailwind CSS v4.3.3 design tokens, such as the color palettes, spacing, type scale, radius, shadows and animations, ascss.createStaticvalues; each value is compiled into the styles that read it, so the package adds nothing to the bundle - Feat: a definition read by name through a namespace import, such as
tokens.blue[500]afterimport * as tokens from './tokens', compiles as it does throughimport { blue }; a string key, destructuring, a rest element or the namespace passed as a whole still stops the build and asks for a named import - Fix: an import whose names are all compiled away, such as a
css.createStaticimport read only insidecss.create, is removed from the output, so the bundler no longer resolves or loads that module; an import still read at runtime, rendered as a component or re-exported is kept - Fix: reading a module's exports before the first project scan, as
resolveExportandresolveExportValuecan, no longer leaves that module out of the scan - Fix:
no-combinatorchecks only thecss.createStaticvalues that start with:or[, the ones that become a selector when used as a key, so a value with spaces, such as a shadow or a font stack, is no longer reported - Update:
no-unknown-css-propertiesacceptsfit-tolerance,min-sizeandmax-size, from the latest MDN and webref data