Vite
Set up yak in a Vite app with the viteYak plugin and get styled-components syntax with build-time CSS extraction in React Router, TanStack Start and more.
yak supports Vite through the viteYak plugin, and any Vite-based framework works out of the box.
This page shows how to:
- Configure Vite to use yak
- Define a theme context for
YakThemeProvider - Migrate from styled-components
- Start from scratch if you don't use any CSS-in-JS yet
Install dependencies
Install @yak/react alongside Vite and React (if you haven't already):
npm i @yak/react
# or
pnpm add @yak/react
# or
yarn add @yak/react
# or
bun add @yak/reactConfigure Vite
Add the viteYak plugin to your vite.config.ts (or .js). It works together with @vitejs/plugin-react-swc or @vitejs/plugin-react.
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react-swc";
import { viteYak } from "@yak/react/vite";
export default defineConfig({
//...
plugins: [viteYak(), react()], // ideally this is before the react plugin
});You can pass the same options you would use in withYak:
viteYak({
// compact class names in production
minify: process.env.NODE_ENV === "production",
// optional prefix for generated identifiers
prefix: "my-app",
// optional custom path to your yak context file
// (relative to the project root)
contextPath: "yak.context",
// base path for CSS virtual module resolution (default: Vite's root)
// useful in monorepo setups where source files live outside the Vite root
// relative paths are resolved from Vite's project root
basePath: "../..",
// enable logging of transformed TS/CSS
debug: false,
});Theme context (yak.context.ts)
If you want to use YakThemeProvider / useTheme, create a yak.context.ts file in your project root.
The Vite plugin automatically aliases @yak/react/context/baseContext to this file.
export function getYakThemeContext() {
if (typeof document !== "undefined") {
const cookies = document.cookie.split(";");
const highContrastCookie = cookies.find((cookie) => cookie.trim().startsWith("highContrast="));
const highContrast = highContrastCookie ? highContrastCookie.split("=")[1] === "true" : false;
return { highContrast };
}
// server / SSR fallback
return { highContrast: false };
}
declare module "@yak/react" {
export interface YakTheme extends ReturnType<typeof getYakThemeContext> {}
}Then wrap your app in YakThemeProvider and read the theme from @yak/react/context/baseContext:
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import App from "./App";
import { YakThemeProvider } from "@yak/react";
import { getYakThemeContext } from "@yak/react/context/baseContext";
import "./globals.css";
createRoot(document.getElementById("root")!).render(
<StrictMode>
<YakThemeProvider theme={getYakThemeContext()}>
<App />
</YakThemeProvider>
</StrictMode>,
);JSX runtime / css prop
If you use the css prop, set the JSX import source to @yak/react to get its types:
Per-file (quick start):
/** @jsxImportSource @yak/react */
import { styled, css } from "@yak/react";
const Title = styled.h1`
${({ $primary }: { $primary?: boolean }) =>
$primary &&
css`
color: teal;
`}
`;Globally via tsconfig / jsconfig:
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "@yak/react"
}
}Migrating from styled-components
If you already use styled-components in a Vite + React app, migration is mostly about imports
(the styled API stays familiar). After adding the viteYak plugin:
import styled, { css, keyframes } from "styled-components";
import { styled, css, keyframes } from "@yak/react";
const Button = styled.button<{ $primary?: boolean }>`
background: #bf4f74;
color: ${({ $primary }) => ($primary ? "white" : "#bf4f74")};
`;Most common patterns (static styles, dynamic props, css blocks, keyframes, attrs, component references)
work the same. For details and edge cases, see the
Migration from styled-components guide.
Starting without any CSS-in-JS
If you don't use any CSS-in-JS today, you can:
- Install
@yak/reactand configureviteYakas shown above. - Start using
styledcomponents alongside your existing CSS files.
import { styled } from "@yak/react";
const Button = styled.button`
padding: 0.5rem 1rem;
border-radius: 9999px;
border: 1px solid currentColor;
background: white;
&:hover {
background: #f3f4f6;
}
`;
export default Button;You can mix yak with regular CSS / CSS Modules. yak styles are extracted at build time and end up in regular CSS files handled by Vite's CSS pipeline.
Yak constant files in Vite
yak supports build-time constants and mixins in special .yak.ts / .yak.tsx files. They run in an isolated
context at build time.
Simple string constants don't need a .yak file. They can live in normal .ts modules and be imported as usual.
.yak files are useful when you want to run a bit of TypeScript/JavaScript at build time
(e.g. generate a design token scale, expand objects, or normalize data) and then inject the
result into your styles.
Example: build-time design tokens
// Base scale for spacing (in px)
const baseSpacing = [0, 4, 8, 12, 16, 24, 32, 40, 48];
export const spacing = Object.fromEntries(
baseSpacing.map((value, index) => [`s${index}`, `${value}px`]),
);
// Generate a simple color ramp
const baseHue = 220;
export const colors = Array.from({ length: 9 }, (_, i) => {
const lightness = 30 + i * 5;
return `hsl(${baseHue}, 80%, ${lightness}%)`;
});Usage in your components:
/** @jsxImportSource @yak/react */
import { styled } from "@yak/react";
import { spacing, colors } from "./theme/tokens.yak";
const Card = styled.div`
padding: ${spacing.s3};
background-color: ${colors[4]};
border-radius: ${spacing.s2};
`;Here, the loops and calculations in tokens.yak.ts run at build time, and only the final
string values are used inside your CSS. This keeps your runtime lean while still letting you
express token generation in regular TypeScript.
Example project
You can find a full Vite example in the repository:
Next steps
- Features: everything you can write with yak
- API reference: all options of
viteYak - Troubleshooting: build errors and missing styles