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.
Configures Tailwind CSS and shadcn/ui for React frontends connecting to Django backends, including dark mode support and theme tokens. Use this when setting up a new React project or adding Tailwind to an existing one.
/plugin marketplace add otoshek/Claude-Code-Toolkit/plugin install claude-code-toolkit@claude-code-toolkitThis skill is limited to using the following tools:
README.mdassets/tailwind-theme.cssscripts/apply-theme.shConfigure 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.
Follow these steps in order:
Install Tailwind CSS and the Vite plugin:
npm --prefix ./frontend tailwindcss @tailwindcss/vite
Configure vite.config.js to enable Tailwind and path aliases:
vite.config.jsimport path from 'node:path'
import tailwindcss from '@tailwindcss/vite'
plugins: [
react(),
tailwindcss(),
]
@/ resolves to src (this relies on the path import above):
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
},
}
Configure the main CSS file to import Tailwind:
src/index.css@import "tailwindcss";
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.
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.
Install the required packages for shadcn/ui component functionality:
npm --prefix ./frontend install class-variance-authority clsx tailwind-merge lucide-react
Create jsconfig.json in the frontend root directory:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}
Create src/lib/utils.js:
import { clsx } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs) {
return twMerge(clsx(inputs))
}
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"
}
}
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:
mcp__shadcn__search_items_in_registries with registries=["@shadcn"] and query="card"mcp__shadcn__search_items_in_registries with registries=["@shadcn"] and query="button"mcp__shadcn__search_items_in_registries with registries=["@shadcn"] and query="navigation-menu"mcp__shadcn__search_items_in_registries with registries=["@shadcn"] and 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
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}",
],
}
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;
}
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>
);
}
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;
Integrate the ThemeToggle component into the navigation bar:
src/components/Navbar.jsx or similar)import ThemeToggle from "@/components/ThemeToggle";
<ThemeToggle /> component in an appropriate location within the navbar, typically in the right section alongside other navigation items:
<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>
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:
jsconfig.json path aliases match vite.config.js aliasestailwind.config.js content paths include all component filesThe Tailwind CSS and shadcn/ui setup is now complete. The project includes:
@/components, @/lib, etc.)This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.