Summary
shadcn/ui failed to install in a Vite + React + JavaScript project because the developer mixed Tailwind v3 installation steps with incompatible Vite configuration. The result was missing Tailwind directives, broken CSS build, and runtime errors.
Root Cause
- Incorrect Tailwind version: Tailwind v3 was installed, but the
postcssandautoprefixerpeer dependencies required by Vite were not aligned. - Missing Tailwind config:
tailwind.config.cjswas not created or referenced correctly invite.config.js. - Improper import of shadcn components: Components were imported before Tailwind utilities were generated, causing class‑name mismatches.
- JavaScript (not TypeScript) project: The official shadcn guide assumes a TypeScript setup; the user tried to copy TS‑specific commands.
Why This Happens in Real Systems
- Documentation gaps: shadcn UI docs target TS/Vite + React; they omit JavaScript‑only nuances.
- Implicit dependencies: Vite’s plugin chain expects
tailwindcssandpostcssto be configured explicitly; otherwise the CSS pipeline is silent. - Assumed conventions: Many tutorials skip creating the
src/app.cssentry point, leading to “no Tailwind classes found” errors.
Real-World Impact
- Development stalls: Teams waste hours troubleshooting missing styles.
- Broken UI: Components render without intended spacing, colors, or responsiveness.
- Increased churn: Junior developers spend time on trial‑and‑error instead of feature work.
- Potential regressions: Subsequent builds may silently drop Tailwind utilities, causing production UI glitches.
Example or Code (if necessary and relevant)
# Install correct versions
npm i -D tailwindcss@latest postcss@latest autoprefixer@latest
npx tailwindcss init -p
# vite.config.js snippet
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
css: {
postcss: {
plugins: [require('tailwindcss'), require('autoprefixer')],
},
},
});
/* src/index.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
// src/main.jsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import { Button } from '@/components/ui/button';
ReactDOM.createRoot(document.getElementById('root')).render(
);
How Senior Engineers Fix It
- Validate dependency graph: Run
npm ls tailwindcss postcss autoprefixerto ensure versions match Vite’s expectations. - Create a minimal Tailwind pipeline: Generate
tailwind.config.cjsandpostcss.config.cjswith default exports, then reference them invite.config.js. - Import CSS early: Ensure the Tailwind entry file (
index.css) is imported before any shadcn component. - Use the shadcn CLI correctly: Run
npx shadcn-ui@latest add buttonafter Tailwind is functional; the CLI will scaffold component files that reference the correct CSS classes. - Add a sanity test: Create a plain
<div className="bg-primary p-4">test</div>to confirm Tailwind is active before integrating shadcn.
Why Juniors Miss It
- Over‑reliance on video tutorials that skip error‑checking steps.
- Assuming TypeScript steps work unchanged in JavaScript (e.g.,
tsconfig.jsonreferences). - Neglecting the order of imports—CSS must be loaded before component code.
- Missing the “install‑tailwind‑via‑vite” checklist, leading to silent configuration failures.