Skip to content
lynstackrecipe

lynstack recipe

Variants in, styles out.

Fast, type-safe recipes that map a component's variants to its class names, its React Native styles, or any value you can combine.
npm install @lynstack/class-recipe
button.ts
import { cva } from "@lynstack/class-recipe";
const button = cva({
base: "rounded-md",
variants: {
tone: {
neutral: "bg-gray-100 text-gray-900",
danger: "bg-red-600 text-white",
},
size: { sm: "h-8 px-3", md: "h-10 px-4" },
},
defaultVariants: { size: "md" },
});
button({ tone: "danger" });
// => "rounded-md bg-red-600 text-white h-10 px-4"

Packages

Pick the package for your values

Each package makes recipes for one kind of value. They are all built on the same engine, so their variants, cache, and types work the same way.

Agent skills

Teach your coding agent the recipes

class-recipe and native-recipe ship agent skills that teach Claude Code, Codex, Cursor, and other agents to write recipes the way these docs recommend.

Terminal window
npx skills add lynstack/recipe --skill class-recipe
npx skills add lynstack/recipe --skill native-recipe

Why recipe

Compiled once, a lookup after that

  • Fast

    9× the calls per second of class-variance-authority. A recipe compiles its config once and caches each selection, so a call is a lookup.

  • Type-safe

    Variants, options, and slots are inferred from the config. An unknown option is a type error, and a variant without a default is required.

  • Your join

    Bring twMerge or any join of your own. It runs once per selection, not on every call.

  • One engine

    Every package shares the variants, the cache, and the types of one engine, so a recipe behaves the same whatever it returns.