# Upgrade a Next.js App to Tailwind CSS v4

Yes. An agent moves your Next.js app from Tailwind 3 to 4 in a cloud sandbox and opens a pull request with before and after screenshots of each page.

[Run this on Rush](https://cloud.getrush.ai/run/migrate-tailwind-v4/nextjs/), in a Project that has your repository.

## What the agent does

The agent clones the repository into its own sandbox and takes the "before" pictures first, because a Tailwind upgrade is judged by what the pages look like, not by whether the build passes. In a Next.js app like shadcn-ui/taxonomy, `package.json` has `tailwindcss` `^3.3.1`, `autoprefixer`, `postcss`, the `tailwindcss-animate` and `@tailwindcss/typography` plugins, and `next` at `13.3.2-canary.13`; `postcss.config.js` lists `tailwindcss: {}` and `autoprefixer: {}`; and `tailwind.config.js` is a CommonJS file with `darkMode: ["class"]`, a `container` setting, colors mapped to CSS variables such as `hsl(var(--border))`, and accordion keyframes. The build is `contentlayer build && next build` with pnpm. It starts the app, then opens the home page, `/pricing`, a page under `/docs` and `/dashboard` in the sandbox's browser, in light and in dark theme, and saves each screenshot.

Then it runs the official upgrade tool, `npx @tailwindcss/upgrade`. One thing has to change first: the tool needs Node 20 or newer, and taxonomy's `.nvmrc` says `v16.18.0`, so the agent runs the upgrade on a current Node and puts the `.nvmrc` change in the pull request with the reason, rather than leaving a project pinned to a Node version its new toolchain cannot run on. The tool replaces the three `@tailwind` directives at the top of `styles/globals.css` with `@import "tailwindcss"`, moves the theme from `tailwind.config.js` into CSS, swaps `tailwindcss` and `autoprefixer` in the PostCSS config for `@tailwindcss/postcss`, and renames utilities across `app/` and `components/`.

Those renames are where a careful upgrade earns its keep, because several v3 names still exist in v4 and mean something smaller. A bare `shadow` becomes `shadow-sm`, `shadow-sm` becomes `shadow-xs`, `rounded` becomes `rounded-sm`, `rounded-sm` becomes `rounded-xs`, `blur-sm` becomes `blur-xs`, `outline-none` becomes `outline-hidden`, and a bare `ring` changes from 3px to 1px, so `ring` becomes `ring-3` to look the same. taxonomy uses all of these in its components. The agent reads the tool's diff for each rename instead of trusting it, and checks the things it does not cover: the two plugins now load with `@plugin` lines in CSS, the `.dark` class strategy needs a `dark` custom variant, and the class names inside `content/**/*.{md,mdx}` that `tailwind.config.js` scanned explicitly still need to be found, with an `@source` line if they are not.

Last, it builds with `pnpm build`, starts the app again and takes the same screenshots of the same pages in both themes. It compares each pair, and for every difference it finds the cause (a border that now defaults to `currentColor`, a ring that got thinner, a placeholder color that changed), fixes it in CSS or in the markup, and takes the screenshot again until the pair matches or the difference is one it can explain as intended.

## Start it with one API call

`POST https://api.prix.dev/o/{org}/sessions`

```json
{
  "agent": "claude",
  "input": "Upgrade this Next.js app from Tailwind CSS 3 to 4. Before changing anything, start the app and take screenshots in the browser of the home, pricing, docs and dashboard pages in light and dark theme. If the Node version the project pins is older than the upgrade tool needs, update it and say why. Run npx @tailwindcss/upgrade, then review its changes: the CSS-first config, the PostCSS plugin, plugins loaded with @plugin, the dark mode variant, content paths that need @source, and every renamed utility (shadow, rounded, blur, outline-none, ring). Build the app, start it, take the same screenshots, and compare each pair. Fix every visual difference that is not intended and take the screenshot again. Open a pull request with each before and after pair, a list of the differences you found and how you fixed each one, and the build output.",
  "resources": [
    {
      "url": "https://github.com/your-org/your-app"
    }
  ]
}
```

1. **Get an API key.** In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
2. **Send the request.** POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
3. **Read what came back.** Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.

## What comes back

What comes back is a pull request on its own branch. The diff deletes or shrinks `tailwind.config.js`, rewrites the head of `styles/globals.css` with `@import "tailwindcss"`, the theme and the `@plugin` lines, replaces the PostCSS config's plugins with `@tailwindcss/postcss`, updates `package.json` and the lockfile, and renames utilities across `app/` and `components/`. If the Node version had to move, `.nvmrc` changes too. The description holds the screenshot pairs for each page and theme, the list of visual differences with the fix for each, and the final `pnpm build` output.

The proof is the screenshots and the transcript behind them. Every command the agent ran is kept with its output: the first app start, the upgrade tool's own log, each build, and each screenshot taken before and after a fix, so a reviewer can see a difference appear and then go away. Your repository's own checks run on the pull request as well, such as `next lint`, if a workflow runs it.

Before merging, a reviewer looks at the screenshot pairs, then reads the rename diff in the components they know best, since a utility that renders differently on hover or focus does not show in a static screenshot. It is also worth checking the browsers you support: Tailwind 4 targets current Safari, Chrome and Firefox releases, and an app with users on older browsers should know that before it ships.

## Run it on every Next.js app still on Tailwind 3

A team with several apps on Tailwind 3 can upgrade them one run each: a `POST /o/{org}/sessions` per repository with that repository in `resources` and this prompt as `input`, each in its own sandbox with its own browser. An `Idempotency-Key` per repository makes a retried request return the run it already started.

A key runs up to its `max_concurrent` sessions at once (4 by default), and a webhook on it posts `run.completed` or `run.failed` when each turn finishes, with the `session_url` to read the result. A reviewer who wants another page captured sends a follow-up message to the same session, and the parked sandbox wakes with the app already installed.

## Why run it on Rush?

A Tailwind upgrade is a visual change dressed as a dependency bump. Checking it means running the app twice, on the old and the new styles, and looking at the same pages in the same themes at the same size. On a laptop that means a second checkout or a stash, two dev servers, and a person clicking through pages while doing other work. In a Rush sandbox the agent has the app, its database and a browser to itself, takes the screenshots at a fixed viewport, and keeps both sets.

The pull request carries its own evidence: the before and after screenshots, the upgrade tool's log, and every build, all in the transcript next to the commands. A reviewer does not have to trust that "nothing changed"; they can see the pairs and the list of differences the agent found and fixed, and ask for more pages with one follow-up message.

## Frequently asked questions

### Can it screenshot pages behind a login?

Yes, if the sandbox can sign in. For an app like taxonomy, whose dashboard needs a NextAuth session and a MySQL database, the agent can start MySQL in the sandbox, seed a user and sign in as it. If sign-in depends on an outside provider it cannot reach, it says which pages it could not capture.

### Will it keep my tailwind.config.js?

The upgrade tool moves the theme into CSS, which is the v4 default. Tailwind 4 can still load a JavaScript config with an `@config` line, so if you would rather keep the file, say so in the input and the agent leaves it in place and points the CSS at it.

### What about shadcn/ui components?

They are your own files under `components/`, so the upgrade tool renames their utilities like any other. The agent reviews those renames in particular, because shadcn/ui components lean on `ring`, `rounded` and `shadow`, whose v3 names mean something smaller in v4.

### Does it upgrade Next.js too?

No. The prompt changes Tailwind and only what Tailwind needs, such as the Node version the upgrade tool runs on. Upgrading Next.js is a separate change with its own risks, and keeping it out of this pull request keeps the screenshot comparison about styles alone.
