Awesome-omni-skill tailwind-setup
Configure Tailwind CSS and shadcn/ui for React frontends with Django backends, including dark mode support and theme tokens. This skill should be used when setting up a new React project or adding Tailwind to an existing one.
git clone https://github.com/diegosouzapw/awesome-omni-skill
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/development/tailwind-setup" ~/.claude/skills/diegosouzapw-awesome-omni-skill-tailwind-setup-8a9f75 && rm -rf "$T"
skills/development/tailwind-setup/SKILL.mdPurpose
Configure Tailwind CSS with shadcn/ui for React frontends connecting to Django backends. This setup includes dark mode support, theme tokens, and shadcn/ui component integration. The configuration enables automatic dark mode switching and provides a foundation for building consistent, themeable user interfaces.
Setup Process Overview
Follow these steps in order:
- Install Dependencies
- Configure Vite for Django Backend
- Setup Tailwind in CSS
- Apply Base Theme (Required for dark mode support)
- Setup shadcn/ui
- Implement Dark Mode with Toggle
- Verify Setup and Check for Errors
Step 1: Install Dependencies
Install Tailwind CSS and the Vite plugin:
npm --prefix ./frontend tailwindcss @tailwindcss/vite
Step 2: Configure Vite for Django Backend
Configure
vite.config.js to enable Tailwind and path aliases:
- Read existing
vite.config.js - Add the required imports at the top (keep the existing React import):
import path from 'node:path' import tailwindcss from '@tailwindcss/vite' - Update the plugins array so Tailwind runs alongside React:
plugins: [ react(), tailwindcss(), ] - Define the alias block in the same file so
resolves to@/
(this relies on thesrc
import above):pathresolve: { alias: { '@': path.resolve(__dirname, './src'), }, }
Step 3: Setup Tailwind in CSS
Configure the main CSS file to import Tailwind:
- Read existing
src/index.css - Replace the entire contents with the Tailwind import:
@import "tailwindcss";
Step 4: Apply Base Theme
Apply the base theme by running the bundled script from the project root directory at:
scripts/apply-theme.sh
Apply the base theme by running the script from the skill's bundled resources at:
scripts/apply-theme.sh within this skill's directory.
The script requires requires the frontend directory path (relative to project root) as an argument.
- Run the theme script from project root:
bash <path-to-skill>/scripts/apply-theme.sh frontend
The script appends shadcn/ui's design tokens (from
assets/tailwind-theme.css, in the skill's bundled resources) to src/index.css, adding support for typography, colors, and automatic dark mode.
Step 5: Setup shadcn/ui
5a. Install shadcn/ui Dependencies
Install the required packages for shadcn/ui component functionality:
npm --prefix ./frontend install class-variance-authority clsx tailwind-merge lucide-react
5b. Create jsconfig.json for Path Aliases
Create
jsconfig.json in the frontend root directory:
{ "compilerOptions": { "baseUrl": ".", "paths": { "@/*": ["./src/*"] } } }
5c. Create Utility Helper Function
Create
src/lib/utils.js:
import { clsx } from "clsx" import { twMerge } from "tailwind-merge" export function cn(...inputs) { return twMerge(clsx(inputs)) }
5d. Create components.json Configuration
Create
components.json in the frontend root directory:
{ "$schema": "https://ui.shadcn.com/schema.json", "style": "new-york", "rsc": false, "tsx": false, "tailwind": { "config": "tailwind.config.js", "css": "src/index.css", "baseColor": "neutral", "cssVariables": true, "prefix": "" }, "aliases": { "components": "@/components", "utils": "@/lib/utils", "ui": "@/components/ui", "lib": "@/lib", "hooks": "@/hooks" } }
5e. Install shadcn/ui Components
PREREQUISITE: Before installing components, verify their availability and review usage patterns using the shadcn MCP server. This ensures compatibility with the current registry and helps understand proper implementation patterns.
MCP Verification:
Use the shadcn MCP tools to search for each component and confirm it exists in the registry:
withmcp__shadcn__search_items_in_registries
andregistries=["@shadcn"]query="card"
withmcp__shadcn__search_items_in_registries
andregistries=["@shadcn"]query="button"
withmcp__shadcn__search_items_in_registries
andregistries=["@shadcn"]query="navigation-menu"
withmcp__shadcn__search_items_in_registries
andregistries=["@shadcn"]query="alert"
Install Required Components:
Once verified, install the components using the shadcn CLI:
npx --prefix ./frontend shadcn@latest add card npx --prefix ./frontend shadcn@latest add field npx --prefix ./frontend shadcn@latest add input npx --prefix ./frontend shadcn@latest add button npx --prefix ./frontend shadcn@latest add table npx --prefix ./frontend shadcn@latest add navigation-menu npx --prefix ./frontend shadcn@latest add label npx --prefix ./frontend shadcn@latest add separator npx --prefix ./frontend shadcn@latest add alert
Step 6: Implement Dark Mode with Toggle
6a. Configure Tailwind for Class-based Dark Mode
Create or update
tailwind.config.js in the frontend root directory, to enable class-based dark mode:
/** @type {import('tailwindcss').Config} */ export default { darkMode: 'class', content: [ "./index.html", "./src/**/*.{js,jsx}", ], }
6b. Create Theme Context
Create
src/contexts/ThemeContext.jsx:
import { createContext, useContext, useEffect, useState } from "react"; const ThemeContext = createContext({ theme: "system", setTheme: () => null, }); export function ThemeProvider({ children, defaultTheme = "system", storageKey = "theme" }) { const [theme, setTheme] = useState(() => { return localStorage.getItem(storageKey) || defaultTheme; }); useEffect(() => { const root = document.documentElement; root.classList.remove("dark"); if (theme === "system") { const systemTheme = window.matchMedia("(prefers-color-scheme: dark)").matches; if (systemTheme) { root.classList.add("dark"); } return; } if (theme === "dark") { root.classList.add("dark"); } }, [theme]); const value = { theme, setTheme: (newTheme) => { localStorage.setItem(storageKey, newTheme); setTheme(newTheme); }, }; return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>; } export function useTheme() { const context = useContext(ThemeContext); if (context === undefined) { throw new Error("useTheme must be used within a ThemeProvider"); } return context; }
6c. Create Theme Toggle Button Component
Create
src/components/ThemeToggle.jsx:
import { Moon, Sun } from "lucide-react"; import { Button } from "@/components/ui/button"; import { useTheme } from "@/contexts/ThemeContext"; export default function ThemeToggle() { const { theme, setTheme } = useTheme(); const toggleTheme = () => { // If currently system or light, switch to dark // If currently dark, switch to light if (theme === "dark") { setTheme("light"); } else { setTheme("dark"); } }; return ( <Button variant="ghost" size="icon" onClick={toggleTheme} aria-label="Toggle theme" className="cursor-pointer" > <Sun className="h-5 w-5 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" /> <Moon className="absolute h-5 w-5 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" /> </Button> ); }
6d. Wrap App with ThemeProvider
Update
src/App.jsx to include the ThemeProvider:
import Router from "./router"; import { ThemeProvider } from "@/contexts/ThemeContext"; function App() { return ( <ThemeProvider defaultTheme="system" storageKey="theme"> <Router /> </ThemeProvider> ); } export default App;
6e. Add Theme Toggle to Navbar
Integrate the ThemeToggle component into the navigation bar:
- Locate the navbar component: Find the main navigation component (commonly in
or similar)src/components/Navbar.jsx - Import the ThemeToggle component:
import ThemeToggle from "@/components/ThemeToggle"; - Add the toggle to the navbar: Place the
component in an appropriate location within the navbar, typically in the right section alongside other navigation items:<ThemeToggle /><nav className="flex items-center justify-between p-4"> <div>{/* Logo and left-side nav items */}</div> <div className="flex items-center gap-4"> {/* Other right-side nav items */} <ThemeToggle /> </div> </nav>
Step 7: Run Build to Check for Compilation Errors
Build the project to verify there are no compilation errors:
npm --prefix ./frontend run build
If the build succeeds, the setup is complete. If there are errors:
- Check for missing imports or incorrect file paths
- Verify all components were installed correctly
- Ensure
path aliases matchjsconfig.json
aliasesvite.config.js - Confirm
content paths include all component filestailwind.config.js
Setup Complete
The Tailwind CSS and shadcn/ui setup is now complete. The project includes:
- Tailwind CSS with Vite integration
- shadcn/ui design tokens and theme variables
- Dark mode support with class-based switching
- Path aliases configured for clean imports (
,@/components
, etc.)@/lib - Core shadcn/ui components installed and ready to use