Migration from next-yak

Markdown

How to move a project from next-yak 9 to @yak/react 10. The API stays the same, so only package names, imports and a few options change.

With version 10, next-yak becomes @yak/react, and the other yak packages move into the @yak scope along with it. The API stays the same: styled, css, keyframes, globalStyle, atoms and the css prop behave exactly as before, so most projects only need new package names, updated imports and a few config changes. The announcement post explains why the package got a new name.

If you can't migrate right away, next-yak 9.x keeps getting bug fixes until the end of 2026, but new features will only land in @yak/react.

Package names

next-yak 9yak 10Works with
next-yak@yak/reactwebpack, Turbopack, Vite, Rsbuild
eslint-plugin-yak@yak/eslint-pluginESLint, Oxlint
storybook-addon-yak@yak/storybookStorybook with webpack or Vite
yak-swc@yak/swcThe SWC plugin behind all of them

Requirements

@yak/react 10 needs:

  • Node.js 22.18 or later
  • Next.js 16.4 or later, Vite 7 or later, or Rsbuild 2 or later
  • React 19

1. Replace the packages

Swap the old packages for the new ones, and install only the ones you used before:

npm uninstall next-yak eslint-plugin-yak storybook-addon-yak
npm install @yak/react
npm install -D @yak/eslint-plugin @yak/storybook

If you have yak-swc as a direct dependency, replace it with @yak/swc.

2. Update the imports

Replace every next-yak import with @yak/react. The subpaths don't change, so only the package name moves:

import { styled, css } from "next-yak";
import { styled, css } from "@yak/react";

import { withYak } from "next-yak/withYak";
import { withYak } from "@yak/react/withYak";

import { viteYak } from "next-yak/vite";
import { viteYak } from "@yak/react/vite";

import { pluginYak } from "next-yak/rsbuild";
import { pluginYak } from "@yak/react/rsbuild";

import { getYakThemeContext } from "next-yak/context/baseContext";
import { getYakThemeContext } from "@yak/react/context/baseContext";

Search the whole project, not only your source files, because package.json, TypeScript paths and the Storybook or Jest config often reference the package name too.

3. Update the theme type

If you add types to the theme, change the module name in the declaration:

yak.context.ts
declare module "next-yak" {
declare module "@yak/react" {
  export interface YakTheme {
    color: string;
  }
}

This one is easy to miss, because TypeScript won't complain about the old name. The declaration stops applying, which leaves the theme type empty and theme.color untyped.

4. Update the JSX import source

If you use the css prop, change the JSX import source in tsconfig.json:

tsconfig.json
{
  "compilerOptions": {
    "jsxImportSource": "next-yak"
    "jsxImportSource": "@yak/react"
  }
}

Files that set the JSX import source with a pragma need the same change:

/** @jsxImportSource next-yak */
/** @jsxImportSource @yak/react */

5. Update the options

Since @yak/react always writes plain CSS, the options experiments.transpilationMode and experiments.suppressDeprecationWarnings are gone. The debug option stays but moves out of experiments to the top level:

next.config.mjs
export default withYak(
  {
    experiments: {
      transpilationMode: "Css",
      suppressDeprecationWarnings: true,
      debug: true,
    },
    debug: true,
  },
  nextConfig,
);

The Vite and Rsbuild plugins take the same options.

6. Remove the :global() wrappers

In next-yak 9, the Next.js webpack setup compiled to CSS Modules, which is why you needed :global() to escape the local scope. @yak/react always compiles to plain CSS, where every selector is already global, so a :global() wrapper now fails the build. Remove the wrapper and keep the selector inside it:

const Wrapper = styled.div`
  :global(.external-class) { 
  .external-class { 
    color: red;
  }
`;

7. Update the lint config

With :global() gone, the css-global-deprecated rule is gone as well, so remove it from your config. All other rules keep their names but switch their prefix from yak/ to @yak/.

For ESLint:

eslint.config.mjs
import yakPlugin from "eslint-plugin-yak";
import yakPlugin from "@yak/eslint-plugin";
import { defineConfig } from "eslint/config";

export default defineConfig([yakPlugin.configs.recommended]);

For Oxlint:

.oxlintrc.json
{
  "jsPlugins": ["eslint-plugin-yak"],
  "jsPlugins": ["@yak/eslint-plugin"],
  "rules": {
    "yak/css-nesting-operator": "error",
    "yak/css-global-deprecated": "warn",
    "yak/enforce-semicolon": "error",
    "yak/style-conditions": "warn",
    "@yak/css-nesting-operator": "error",
    "@yak/enforce-semicolon": "error",
    "@yak/style-conditions": "warn"
  }
}

If you configure individual rules in ESLint, update their prefix the same way. The ESLint plugin page has the full configuration.

8. Update Storybook

.storybook/main.ts
const config = {
  addons: [
    "storybook-addon-yak",
    "@yak/storybook",
  ],
};

9. Jest with next/jest

@yak/react ships as ESM only. If you test with next/jest, add it to transpilePackages in your Next.js config so that Jest can load it:

next.config.mjs
const nextConfig = {
  transpilePackages: ["@yak/react"],
};

Check the result

Start the dev server and check that your styles show up. A missing style usually means a file still imports from next-yak. If something else breaks, please open an issue so we can look into it.