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)