Tailwind utility classes render in development but are stripped from the production bundle
appears when:After `next build` or any bundler step that runs Tailwind in production mode with a purge-configured content array
Tailwind CSS not working in production
Tailwind's production build emits only classes it can statically see. If the content array misses a folder or a class is built from a template string, those utilities never ship.
content array (v3) or with @source directives (v4), and safelist class names you build from template strings. Never rely on dev mode to catch this.Quick fix for Tailwind not working in production
01// tailwind.config.js (v3) — list every folder that renders class names02/** @type {import('tailwindcss').Config} */03module.exports = {04 content: [05 "./src/**/*.{js,ts,jsx,tsx,mdx}",06 "./app/**/*.{js,ts,jsx,tsx,mdx}",07 "./components/**/*.{js,ts,jsx,tsx,mdx}",08 // include any package that exports class-bearing JSX09 "./node_modules/@myorg/ui/dist/**/*.{js,mjs}",10 ],11 safelist: [12 // only classes built at runtime — everything else Tailwind finds on its own13 { pattern: /^bg-(red|green|blue|amber)-(400|500|600)$/ },14 ],15 theme: { extend: {} },16 plugins: [],17};Deeper fixes when the quick fix fails
01 · Tailwind v4 — replace tailwind.config.js with @source in CSS
01/* app/globals.css — Tailwind v4 source declarations */02@import "tailwindcss";03 04@source "../src/**/*.{js,ts,jsx,tsx,mdx}";05@source "../app/**/*.{js,ts,jsx,tsx,mdx}";06@source "../components/**/*.{js,ts,jsx,tsx,mdx}";07/* third-party UI library with class names */08@source "../node_modules/@myorg/ui/dist/**/*.{js,mjs}";09 10@theme {11 --color-lime: oklch(85% 0.2 130);12}02 · Refactor dynamic classes to a literal lookup
01// BEFORE — Tailwind cannot see this class02function Badge({ color }: { color: "red" | "green" }) {03 return <span className={`bg-${color}-500`}>ok</span>;04}05 06// AFTER — every possible class is a literal the scanner finds07const badgeClass = {08 red: "bg-red-500 text-red-50",09 green: "bg-green-500 text-green-50",10} as const;11 12function Badge({ color }: { color: keyof typeof badgeClass }) {13 return <span className={badgeClass[color]}>ok</span>;14}03 · Write a regression Playwright test that checks computed style
01// e2e/tailwind.spec.ts — fails if the utility is purged02import { test, expect } from "@playwright/test";03 04test("hero has lime background in production", async ({ page }) => {05 await page.goto("/");06 const hero = page.locator('[data-testid="hero-cta"]');07 const bg = await hero.evaluate((el) => getComputedStyle(el).backgroundColor);08 // lime-500 in rgb — if Tailwind purges the class, this becomes rgba(0,0,0,0)09 expect(bg).toBe("rgb(132, 204, 22)");10});Why AI-built apps hit Tailwind not working in production
Tailwind's JIT compiler walks every file in the content array, extracts class names it recognizes, and emits exactly that set into the final CSS bundle. In dev mode the compiler generates utilities on demand as you type, so every class works whether the array is correct or not. The first time you hit next build or any real production build, Tailwind enforces the list. Classes in files outside the list get purged. Your page ships without the styles that worked five minutes ago on localhost.
AI builders like Lovable, Bolt, and v0 scaffold a content array with ./src/**/* and stop. Later you add an app/ directory or pull components from an @myorg/ui package inside node_modules. Neither is covered. Every class inside those files disappears on build. The error does not surface in dev because JIT papers over it.
The second common source is dynamic class names. A component writes className={`bg-${color}-500`}` where color is a variable. The scanner reads the literal string in the source file, sees no complete class, emits nothing. In dev it works because JIT picks up bg-red-500 the moment it renders. In prod the bundle never contains it. Fix by mapping the variable to a literal lookup table or by safelisting the pattern in the config.
The third source is Tailwind v4 migrations. v4 dropped tailwind.config.js and uses @source directives inside your main CSS. If you installed v4 but left the v3 config in place, Tailwind falls back to defaults, ignores your paths, and produces a tiny bundle. The symptom looks identical to a misconfigured content array.
Tailwind not working in production by AI builder
How often each AI builder ships this error and the pattern that produces it.
| Builder | Frequency | Pattern |
|---|---|---|
| Lovable | Every scaffold with Tailwind | Content array only lists ./src/**/* — misses /app and node_modules UI packages |
| Bolt.new | Common | Template-literal class names like `bg-${color}-500` never safelisted |
| v0 | Common | Mixes Tailwind v3 config with v4 imports — neither takes effect |
| Cursor | Sometimes | Forgets to rerun `next build` after editing tailwind.config.js |
| Replit Agent | Rare | PostCSS plugin order wrong — autoprefixer runs before Tailwind |
Related errors we fix
Stop Tailwind not working in production recurring in AI-built apps
- →Run `next build && next start` locally before every deploy — dev mode hides purge failures.
- →Never build class names with template literals — map variables to literal class lookups.
- →Add a Playwright visual test per critical component so purge regressions fail CI.
- →Pin your Tailwind version in package.json and document v3 vs v4 in README.
- →Audit the content array (or @source directives) the moment you add a new source folder.
Still stuck with Tailwind not working in production?
Tailwind not working in production questions
Why do my Tailwind classes work in development but disappear in production?+
How do I safelist dynamic class names in Tailwind?+
What is the difference between Tailwind v3 and v4 config for missing styles?+
Can PostCSS order cause Tailwind to break in production?+
How long does a full Tailwind production fix take?+
Ship the fix. Keep the fix.
Emergency Triage restores service in 48 hours. Break the Fix Loop rebuilds CI so this error cannot ship again.
Hyder Shah leads Afterbuild Labs, shipping production rescues for apps built in Lovable, Bolt.new, Cursor, Replit, v0, and Base44. our rescue methodology.