🚀 React + Vite + Tailwind CSS + Shadcn UI Setup (vanillaJS)

Published: (May 9, 2026 at 09:39 PM EDT)
5 min read
Source: Dev.to

Source: Dev.to

Cover image for React + Vite + Tailwind CSS + Shadcn UI Setup (vanillaJS)

Nabin Kandel

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:

OptionChoice
FrameworkReact
VariantJavaScript

✅ 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
PackagePurpose
tailwindcssUtility‑first CSS framework
@tailwindcss/viteFirst‑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 like import 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/vite you 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
QuestionRecommended choice
StyleNew York or Default
Base colorSlate (neutral & accessible)
CSS variablesYes (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 code
  • src/components/ – Custom composables (e.g., UserProfile.jsx, NavBar.jsx)
  • src/app/ – Shadcn UI primitives (e.g., button.tsx, dialog.tsx)

🛠️ Troubleshooting Quick Fixes

IssueSolution
@/ imports not workingRestart VS Code; ensure jsconfig.json is at the project root
❌ Tailwind classes not applyingVerify @import "tailwindcss" is present in src/index.css
❌ Shadcn components look unstyledMake sure index.css is imported in src/main.jsx
❌ Vite server won’t startRun npm run dev -- --force to clear the HMR cache
❌ Button has no hover effectEnsure 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" in tailwind.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!

0 views
Back to Blog

Related posts

Read more »