🚀 React + Vite + Tailwind CSS + Shadcn UI Setup (vanillaJS)
Source: Dev.to

A complete step‑by‑step guide to quickly set up React + Vite + Tailwind CSS + Shadcn UI with clean @/... alias imports — no TypeScript required!
⏱️ Time to complete: ~10 minutes
🎯 Result: Production‑ready React app with beautiful, accessible components
🧩 Step 1 – Create a Vite + React project
npm create vite@latest my-app
cd my-app
When prompted, select:
| Option | Choice |
|---|---|
| Framework | React |
| Variant | JavaScript |
✅ Vite will generate a lean, fast React starter with HMR (Hot Module Replacement) out of the box.
🌀 Step 2 – Install dependencies
npm install
npm install tailwindcss @tailwindcss/vite
| Package | Purpose |
|---|---|
tailwindcss | Utility‑first CSS framework |
@tailwindcss/vite | First‑party Vite plugin for Tailwind (no PostCSS config needed!) |
🎨 Step 3 – Configure vite.config.js
Replace the entire contents of vite.config.js with:
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import tailwindcss from "@tailwindcss/vite";
import path from "path";
// https://vite.dev/config/
export default defineConfig({
plugins: [
tailwindcss(),
react({
babel: {
plugins: [["babel-plugin-react-compiler"]], // ✅ Optional: React Compiler for perf
},
}),
],
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"), // ✅ Enable @/ imports
},
},
});
Why this matters
@tailwindcss/vite→ Compiles Tailwind at build time (faster than PostCSS).@alias → Import likeimport Button from "@/components/ui/button"instead of long relative paths.
⚙️ Step 4 – Add jsconfig.json for editor support
Create jsconfig.json at the project root:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
}
Benefits
- ✅ VS Code autocomplete for
@/imports - ✅ ESLint/Prettier understand your alias paths
- ✅ No more “Cannot find module” warnings
🪄 Step 5 – Import Tailwind in your CSS
Open (or create) src/index.css and add:
@import "tailwindcss";
🎉 With
@tailwindcss/viteyou don’t need the classic@tailwind base; @tailwind components; @tailwind utilities;– the plugin injects them automatically.
(Optional) Delete or empty src/App.css to avoid conflicting default styles.
🌈 Step 6 – Initialize Shadcn UI
npx shadcn@latest init
| Question | Recommended choice |
|---|---|
| Style | New York or Default |
| Base color | Slate (neutral & accessible) |
| CSS variables | Yes (for theming) |
Add the first components:
npx shadcn@latest add button card input
✅ Components are placed in src/components/ui/ – fully customizable, accessible, and Tailwind‑powered.
💻 Step 7 – Test your setup
Replace src/App.jsx with:
import { Button } from "@/components/ui/button";
import {
Card,
CardContent,
CardHeader,
CardTitle,
} from "@/components/ui/card";
export default function App() {
return (
<div className="p-4">
<Card>
<CardHeader>
<CardTitle>🎉 Setup Successful!</CardTitle>
</CardHeader>
<CardContent>
<p>You're now running React + Vite + Tailwind + Shadcn UI.</p>
<Button>Click Me</Button>
<Button variant="secondary">Secondary Action</Button>
</CardContent>
</Card>
</div>
);
}
Start the development server:
npm run dev
Visit http://localhost:5173 – you should see a beautifully styled card with Shadcn buttons!
✅ Final project structure
my-app/
├── public/
├── src/
│ ├── components/
│ │ └── ui/ # 🎨 Shadcn components (button, card, input…)
│ ├── App.jsx # 🏠 Main app component
│ ├── index.css # 🎨 Tailwind import
│ └── main.jsx # ⚡ React entry point
├── index.html
├── vite.config.js # ⚙️ Vite + Tailwind + alias config
├── jsconfig.json # 🧠 Editor alias support
├── tailwind.config.js # 🎨 Auto‑generated by Shadcn (optional to tweak)
├── package.json
└── …
🧭 Pro tip
Keep all Shadcn UI components inside src/components/ui/. This makes it easy to locate, customize, and extend your design system as the project grows.
📦 Project Structure (Quick Recap)
src/– Your app codesrc/components/– Custom composables (e.g.,UserProfile.jsx,NavBar.jsx)src/app/– Shadcn UI primitives (e.g.,button.tsx,dialog.tsx)
🛠️ Troubleshooting Quick Fixes
| Issue | Solution |
|---|---|
❌ @/ imports not working | Restart VS Code; ensure jsconfig.json is at the project root |
| ❌ Tailwind classes not applying | Verify @import "tailwindcss" is present in src/index.css |
| ❌ Shadcn components look unstyled | Make sure index.css is imported in src/main.jsx |
| ❌ Vite server won’t start | Run npm run dev -- --force to clear the HMR cache |
| ❌ Button has no hover effect | Ensure tailwind.config.js includes the correct content paths (Shadcn auto‑generates them) |
🧪 Bonus: Add a Dark‑Mode Toggle (Optional)
Shadcn supports theming out of the box! Add the following to src/App.jsx:
import { useEffect, useState } from "react";
import { Button } from "@/components/ui/button";
export default function App() {
const [dark, setDark] = useState(false);
useEffect(() => {
document.documentElement.classList.toggle("dark", dark);
}, [dark]);
return (
<div className="p-4">
<Button
onClick={() => setDark(!dark)}
variant="outline"
>
{dark ? "☀️ Light Mode" : "🌙 Dark Mode"}
</Button>
</div>
);
}
Tip: Set
darkMode: "class"intailwind.config.js(Shadcn does this by default).
🔗 Helpful Resources
🎯 Key Takeaways
- ✅ Vite – Blazing‑fast dev server & build tool
- ✅
@tailwindcss/vite– Simpler Tailwind setup (no PostCSS needed) - ✅
@/aliases – Cleaner, scalable imports - ✅ Shadcn UI – Production‑ready, accessible components (you own the code)
- ✅ JavaScript‑first – No TypeScript overhead for quick prototyping
🙌 If this guide helped you ship faster, give it a ❤️, share it with your team, or drop a comment about what you’re building!
