When I built an AI-powered chatbot for my portfolio using React, Vite, and Tailwind CSS v4, everything worked beautifully β until deployment.
Once I pushed to Vercel, the build crashed hard.
The cause?
π Mixing Tailwind CSS v3 and v4 components in the same project.
Hereβs what happened, what I learned, and how I fixed it.
π Table of Contents
- The Setup: What I Was Building
- The Mistake: Installing @tailwindcss/typography
- Why It Worked Locally But Failed on Vercel
- The Root Cause: Version Conflicts
- The Solution: Clean Migration to v4
- Custom Typography: Better Than the Plugin
- Complete Setup Guide
- Key Takeaways
π The Setup: What I Was Building
I was creating an AI chatbot for my portfolio with these features:
- Frontend: React 18 + Vite 6
- Styling: Tailwind CSS v4
- AI Integration: Groq API (Llama 3.1 70B Versatile)
- Markdown Rendering:
react-markdown+remark-gfm - Deployment: Vercel
The chatbot needed to render AI messages with bold, italics, code blocks, lists, and links β so I reached for @tailwindcss/typography.
β The Mistake: Installing @tailwindcss/typography
I ran this:
npm install @tailwindcss/typography Then updated my component:
{isBot ? ( <div className="prose prose-invert prose-sm md:prose-base"> <ReactMarkdown remarkPlugins={[remarkGfm]}> {message.text} </ReactMarkdown> </div> ) : ( <div className="text-sm md:text-base">{message.text}</div> )} Locally, everything worked perfectly.
AI responses looked clean and styled β until Vercel rejected the build.
π€ Why It Worked Locally But Failed on Vercel
Locally, the dev server was lenient:
- Vite dev server ignores strict dependency rules
- Cached dependencies hid conflicts
- Development builds donβt tree-shake or optimize
But Vercelβs production build was strict:
Error: The `@tailwindcss/typography` plugin is designed for Tailwind CSS v3.x but you are using Tailwind CSS v4.x. These versions are incompatible. Vercel installs fresh dependencies and performs strict checks β so it caught what local dev ignored.
π The Root Cause: Version Conflicts
In package.json, I had:
"devDependencies": { "tailwindcss": "^4.1.14" } But running this:
npm list tailwindcss Revealed this:
βββ tailwindcss@4.1.14 βββ¬ @tailwindcss/typography@0.5.10 βββ tailwindcss@3.4.1 β Hidden dependency! The typography plugin pulled in Tailwind v3, creating a version conflict.
| Feature | Tailwind v3 | Tailwind v4 |
|---|---|---|
| Config | tailwind.config.js | CSS-first (@import "tailwindcss") |
| PostCSS | Required | Optional (@tailwindcss/vite) |
| Plugins | JS config | CSS or standalone packages |
| Build | PostCSS | Vite-native |
Mixing both leads to:
- β οΈ Conflicting PostCSS transforms
- β οΈ Duplicate utility generation
- β οΈ Broken configuration detection
- β οΈ Build failures
β The Solution: Clean Migration to v4
Step 1: Remove v3 Dependencies
npm uninstall @tailwindcss/typography postcss autoprefixer rm tailwind.config.js postcss.config.js Step 2: Verify a Clean v4 Setup
Your package.json should include only:
"devDependencies": { "tailwindcss": "^4.1.14", "@tailwindcss/vite": "^4.1.14", "vite": "^6.0.5", "@vitejs/plugin-react": "^4.3.4" } Step 3: Update Vite Config
// vite.config.ts import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' export default defineConfig({ plugins: [react(), tailwindcss()], }) Step 4: Clean CSS Import
/* src/index.css */ @import "tailwindcss"; /* No need for @tailwind base; etc. */ Step 5: Reinstall Everything
rm -rf node_modules package-lock.json npm install π¨ Custom Typography: Better Than the Plugin
Instead of using the plugin, I built my own lightweight typography system β fully compatible with v4, more customizable, and no dependency conflicts.
Example: src/index.css
@import "tailwindcss"; .markdown-prose { line-height: 1.75; color: rgb(229 231 235); } .markdown-prose a { color: rgb(34 211 238); text-decoration: none; transition: color 0.2s; } .markdown-prose a:hover { text-decoration: underline; color: rgb(6 182 212); } .markdown-prose code { background: rgba(255,255,255,0.1); padding: 0.25rem 0.5rem; border-radius: 0.375rem; font-family: 'Courier New', monospace; color: rgb(249 168 212); } .markdown-prose pre { background: rgba(0,0,0,0.3); border-radius: 0.5rem; padding: 1rem; overflow-x: auto; } Component Update:
<div className="markdown-prose"> <ReactMarkdown remarkPlugins={[remarkGfm]}> {message.text} </ReactMarkdown> </div> π§© Complete Setup Guide
1. Install Dependencies
npm install react react-dom react-markdown remark-gfm npm install -D vite @vitejs/plugin-react tailwindcss @tailwindcss/vite 2. Project Structure
my-project/ βββ src/ β βββ index.css β βββ main.tsx β βββ components/ β βββ ChatBot.tsx βββ vite.config.ts βββ package.json 3. Test for Conflicts
npm list tailwindcss β Only v4 should appear
π― Key Takeaways
π‘ What I Learned
- Local β Production β Always test production builds locally.
- Peer Dependencies Matter β
npm list <package>is your friend. - Tailwind v4 β v3 β Itβs a full architecture shift.
- Custom CSS Wins β Fewer dependencies, cleaner builds.
- Vercel Is Strict β And thatβs a good thing.
β Do
- Test production builds before deploy
- Read plugin compatibility docs
- Keep dependencies minimal
β Donβt
- Mix v3 and v4 packages
- Ignore peer dependency warnings
- Assume local dev = production ready
π Resources
π¬ Final Thoughts
Mixing Tailwind v3 and v4 is like trying to run diesel in an electric car β theyβre built differently.
By going all-in with Tailwind v4 and replacing the typography plugin, I ended up with:
- β‘ Faster builds
- π¨ Fully custom styles
- π 100% production compatibility
- π§ Easier maintenance
If youβre upgrading β migrate cleanly, donβt mix.
πββοΈ Questions?
Found this helpful? Drop a comment or connect with me:
π Connect with Me
- πΌ LinkedIn
- π§βπ» GitHub
- πͺ [Portfolio]β Under Contruction π§
- π¦ X (Twitter)
- βοΈ wishotstudio@gmail.com
Last updated: October 2024
Tailwind CSS: v4.1.14 β’ React: 18.3.1 β’ Vite: 6.0.5
Top comments (0)