# Vite (http://yak.js.org/docs/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-dependencies]

Install `@yak/react` alongside Vite and React (if you haven't already):

```bash
npm i @yak/react
# or
pnpm add @yak/react
# or
yarn add @yak/react
# or
bun add @yak/react
```

## Configure Vite [#configure-vite]

Add the `viteYak` plugin to your `vite.config.ts` (or `.js`). It works together with `@vitejs/plugin-react-swc` or `@vitejs/plugin-react`.

```ts title="vite.config.ts"
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`:

```ts
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`) [#theme-context-yakcontextts]

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.

```ts title="yak.context.ts"
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`:

```tsx title="src/main.tsx"
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 [#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):**

```tsx title="App.tsx"
/** @jsxImportSource @yak/react */
import { styled, css } from "@yak/react";

const Title = styled.h1`
  ${({ $primary }: { $primary?: boolean }) =>
    $primary &&
    css`
      color: teal;
    `}
`;
```

**Globally via tsconfig / jsconfig:**

```json title="tsconfig.json"
{
  "compilerOptions": {
    "jsx": "react-jsx",
    "jsxImportSource": "@yak/react"
  }
}
```

## Migrating from styled-components [#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:

```tsx title="src/Button.tsx"
import styled, { css, keyframes } from "styled-components"; // [!code --]
import { styled, css, keyframes } from "@yak/react"; // [!code ++]

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](/docs/migration-from-styled-components) guide.

## Starting without any CSS-in-JS [#starting-without-any-css-in-js]

If you don't use any CSS-in-JS today, you can:

1. Install `@yak/react` and configure `viteYak` as shown above.
2. Start using `styled` components alongside your existing CSS files.

```tsx title="src/Button.tsx"
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-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 [#example-build-time-design-tokens]

```ts title="src/theme/tokens.yak.ts"
// 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:

```tsx title="src/App.tsx"
/** @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 [#example-project]

You can find a full Vite example in the repository:

- Vite example: https://github.com/galaxuslabs/yak/tree/main/examples/vite

## Next steps [#next-steps]

- [Features](/docs/features): everything you can write with yak
- [API reference](/docs/api#viteyak-vite): all options of `viteYak`
- [Troubleshooting](/docs/troubleshooting): build errors and missing styles
