Tailwind JIT classes stripped in Next.js production build when using dynamic template literals for class names
Environment
Next.js 13 app using Tailwind CSS JIT (tailwindcss v3) with app/router, production build on Vercel; codebase uses dynamic className construction via template literals and concatenation (e.g., className={${base} ${cond ? text-${color}-500 : ''}}) and some class names are assembled from variables.
Symptoms
Certain UI elements lose styling on production build (styles present in local dev server). Specific classes like text-red-500 or md:grid-cols-4 are missing from final CSS, causing layout/styling regressions only after next build --production; clearing cache and redeploy doesn't fix until using explicit class names in JSX.
Observations
Tailwind output CSS size is smaller in production; scanning generated CSS shows missing utility selectors that should have been generated; running 'npx tailwindcss -i ./input.css -o ./out.css --content' locally with same content glob produces correct CSS when variable class strings are replaced with literal strings; project's tailwind.config.js content array includes './app//*.{js,jsx,ts,tsx}', './components//*.{js,ts,tsx}', and a custom extractor plugin; PostCSS pipeline is standard; Next.js SWC minifier enabled.
Already attempted
Added safelist entries for missing classes in tailwind.config.js (temporarily restored styling); replaced some dynamic template literal cases with classnames library and explicit strings (fixes those components); disabled SWC minify (no change); examined Vercel build logs for Purge warnings (none); ran tailwind JIT CLI locally replicating production build and reproduced missing classes when using dynamic assembly.
Question
How can Tailwind JIT miss classes constructed via nested template literals at build time in Next.js production builds, and what safe, reversible steps should I follow to make dynamic class names reliable without bloating CSS?
Verified community troubleshooting
No answers yet..