# Introduction

Source: https://plumeria.dev/docs



Plumeria is a compile-time CSS-in-JS library for React. You write style objects in TypeScript, and the compiler turns them into static atomic CSS — while removing every trace of the library from your JavaScript bundle. No runtime code ships, no styles are computed in the browser.

```math
\mathtt{Plumeria(Type)} \xrightarrow{\text{Compilation}} \mathtt{Static\ Atomic\ CSS}
```

Two things follow from compiling instead of injecting. The order of the generated CSS is decided by the compiler's module graph, not by the order a bundler happens to emit chunks — split and rearrange files, and the layout holds. And the way in is also the way out: `npx @plumeria/codemod migrate --from css-modules` brings a CSS Modules project in, and `--from plumeria` takes it back out. See [`@plumeria/codemod`](/docs/api-reference/codemod).

## Usage [#usage]

Styling is straightforward: define styles once with `css.create()`, and the compiler handles everything else. The atomic class names are determined at that point — all that remains is to attach them via the `classStyle` prop.

```tsx
import * as css from "@plumeria/core";

const styles = css.create({
  text: {
    fontSize: 16,
  },
});

export const Footer = () => {
  return <div classStyle={styles.text}>MyText</div>;
};
```

Styles compile to zero across file boundaries, too. You can colocate styles with components or share them across files — structure them to fit your project. The only requirement is that every file using Plumeria imports `@plumeria/core`, which is how the compiler finds it.

```tsx title="styles.ts"
import * as css from "@plumeria/core";

export const styles = css.create({
  common: {
    color: "gray",
  },
});
```

```tsx title="Component.tsx"
import "@plumeria/core";
import { styles } from "./styles";

export const Component = () => {
  return <p classStyle={styles.common}>Shared style</p>;
};
```

### Specificity [#specificity]

The `classStyle` prop accepts arrays, ternaries, and conditional expressions. Merging follows one rule: **the right side wins**. If `isActive` is true, the properties of `active` override the properties of `base` — always.

```tsx title="Component.tsx"
const styles = css.create({
  base: {
    color: "gray",
    fontSize: 16,
  },
  active: {
    color: "blue",
  },
});

classStyle={[styles.base, isActive && styles.active]}
```

Because the compiler controls the merge, the cascade specificity problem disappears entirely. Writing the merge as an operation, where $\oplus$ combines styles left to right, disjoint styles simply concatenate:

$parse(A \oplus B \oplus C) \to \text{"classA classB classC"}$

And when two styles set the same property, the losing atom on the left is filtered out at compile time — it never reaches the output:

$parse(A_{color} \oplus B_{color}) \to \text{"classB"}$

A shorthand against a longhand is the exception: the longhand wins wherever the two meet, in either order. See [Specificity](/docs/reference/specificity).

## Types all the way down [#types-all-the-way-down]

Styling shouldn't require a runtime. Plumeria treats styles as **type schemas** rather than runtime objects — in fact, the package's only entry point is a `.d.ts` file. There is no JavaScript to import:

```json title="package.json"
{
  "name": "@plumeria/core",
  "exports": {
    ".": {
      "types": "./lib/css.d.ts",
    },
  },
}
```

Static styles resolve to class names entirely at compile time. The only dynamic pieces — function keys and variant props — compile down to CSS variables, so even they leave no JavaScript behind. Every API compiles to nothing but static class names and CSS:

* No runtime bundle
* No runtime evaluation
* No runtime parsing
* No runtime dependencies

Of course, "zero-runtime" doesn't claim the cost vanishes — it claims the cost moves. All of the work happens at build time, and the browser only ever receives class names and CSS.

***

To learn what motivated this design, read [Why Plumeria?](/docs/why-plumeria). For integration with bundlers and the full API, see the [API reference](/docs/api-reference) and [Installation](/docs/getting-started/installation).

This site is built with Plumeria. The documentation app lives in the same repository and depends on the workspace packages, so every release is exercised here — and every experiment is tried here — before it ships.
