// Build new Next.js applications or migrate existing frontends (React, Vue, Angular, vanilla JS, etc.) to Next.js + shadcn/ui with systematic analysis and conversion. Enforces shadcn design principles - CSS variables for theming, standard UI components, no hardcoded values, consistent typography/colors. Use for creating Next.js apps, migrating frontends, adopting shadcn/ui, or standardizing component libraries. Includes MCP integration for shadcn documentation and automated codebase analysis.
| name | nextjs-shadcn-builder |
| description | Build new Next.js applications or migrate existing frontends (React, Vue, Angular, vanilla JS, etc.) to Next.js + shadcn/ui with systematic analysis and conversion. Enforces shadcn design principles - CSS variables for theming, standard UI components, no hardcoded values, consistent typography/colors. Use for creating Next.js apps, migrating frontends, adopting shadcn/ui, or standardizing component libraries. Includes MCP integration for shadcn documentation and automated codebase analysis. |
| license | Complete terms in LICENSE.txt |
Build production-grade Next.js applications or systematically migrate existing frontends to Next.js + shadcn/ui following strict design principles and best practices.
This skill handles two primary workflows:
Core Philosophy: 100% adherence to shadcn/ui design principles:
User Request
โโ Creating New Next.js App
โ โโ Follow "Creating New Application" workflow (Phase 3 onwards)
โ
โโ Migrating Existing Codebase
โโ Phase 1: Codebase Analysis
โโ Phase 2: Migration Planning
โโ Phase 3: Next.js + shadcn Setup
โโ Phase 4: Systematic Conversion
โโ Phase 5: Verification & Cleanup
Automated analysis of existing frontend to understand scope and complexity.
Steps:
Deliverables:
Create systematic conversion plan with prioritized batches.
Steps:
Deliverables:
Initialize Next.js infrastructure alongside or replacing existing codebase.
Steps:
Deliverables:
Convert components batch by batch with testing after each batch.
Steps:
Per Batch Workflow:
Deliverables:
Final testing, optimization, and old code removal.
Steps:
Deliverables:
Run the automated analysis script:
python ./scripts/analyze-codebase.py /path/to/existing/codebase
This script will:
Output: codebase-analysis.json with framework metadata
The analysis script automatically generates a component inventory including:
Output: component-inventory.json
Example structure:
{
"components": [
{
"name": "UserCard",
"path": "src/components/UserCard.tsx",
"type": "functional",
"complexity": "simple",
"shadcn_equivalent": "Card",
"hardcoded_values": ["#3b82f6", "16px padding"],
"dependencies": ["react", "styled-components"]
}
]
}
Run the detection script:
bash ./scripts/detect-hardcoded-values.sh /path/to/existing/codebase
This script detects:
#hex, rgb(), rgba(), hsl(), color namesmargin: 20px, padding: 1remstyle={{...}}Output: hardcoded-values-report.md with violations grouped by category
Run the report generator:
python ./scripts/generate-migration-report.py
This combines all analysis data into a comprehensive markdown report:
Output: migration-analysis-report.md
# Frontend Migration Analysis Report
## Executive Summary
[One-paragraph overview: framework, size, complexity]
## Current State Analysis
- **Framework**: React 18.2.0
- **Build Tool**: Vite 4.3.0
- **Component Count**: 47 components
- **Styling**: styled-components + custom CSS
- **State Management**: Redux Toolkit
- **Routing**: React Router v6
## Hardcoded Values Detected
- Colors: 142 instances across 34 files
- Spacing: 89 instances across 28 files
- Custom fonts: 3 non-standard fonts
- Inline styles: 67 instances
## Component Categorization
- **Simple (shadcn mapping exists)**: 28 components
- **Moderate (requires adaptation)**: 13 components
- **Complex (custom development needed)**: 6 components
## Recommended Migration Plan
1. Phase 3: Setup Next.js + shadcn infrastructure
2. Phase 4.1: Convert layout components (Header, Footer, Layout)
3. Phase 4.2: Convert simple UI (Button, Card, Badge โ shadcn equivalents)
4. Phase 4.3: Convert forms (Input, Select โ shadcn/ui Form components)
5. Phase 4.4: Convert complex components (DataTable, Charts)
6. Phase 4.5: Styling standardization (CSS variables)
7. Phase 4.6: Pages and routing
8. Phase 5: Verification and cleanup
## Estimated Effort
- **Total Components**: 47
- **Batches**: 9-10 batches
- **Complexity**: Moderate
Review the component-inventory.json and create a mapping table using the shadcn component reference.
VERY IMPORTANT: Use MCP to discover shadcn components
Before mapping, check if shadcn MCP server is available:
# Check if MCP server is available
# Try accessing https://ui.shadcn.com/docs/mcp
If MCP is not available, install it:
npx shadcn@latest mcp init --client claude
Use MCP to query available components:
Component Mapping Table Template:
| Existing Component | shadcn Equivalent | Complexity | Priority | Notes |
|---|---|---|---|---|
| CustomButton | Button | Low | 1 | Props mostly compatible |
| Modal | Dialog | Medium | 2 | Different API, uses Radix |
| DataTable | Table + DataTable | High | 3 | Requires custom hooks |
| Dropdown | DropdownMenu | Low | 1 | Direct mapping |
| DatePicker | Calendar + Popover | Medium | 2 | Composition pattern |
Load framework-specific migration guide:
./references/react-to-nextjs.md./references/vue-to-nextjs.md./references/angular-to-nextjs.md./references/styling-migration.mdOrganize components into batches following these principles:
Batching Strategy:
Example Batch Plan:
Batch 1: Layout & Structure (Priority: Critical)
Batch 2: Simple UI Components (Priority: High)
Batch 3: Form Components (Priority: High)
Batch 4: Navigation (Priority: Medium)
Batch 5: Data Display (Priority: Medium)
Batch 6: Overlays & Modals (Priority: Medium)
Batch 7: Complex Components (Priority: Low)
Batch 8: Styling Standardization (Priority: Critical)
Batch 9: Pages & Routing (Priority: Critical)
For each batch, identify risks:
Risk Mitigation:
Generate a detailed plan document: migration-plan.md
# Next.js + shadcn Migration Plan
## Project: [Project Name]
## Date: [Current Date]
## Estimated Timeline: [X batches]
## Migration Strategy
### Approach
- Incremental migration with parallel running old and new code
- Batch-based conversion (5-10 components per batch)
- Test after each batch before proceeding
- Feature flag new components during transition
### Success Criteria
- All components use shadcn/ui or shadcn patterns
- Zero hardcoded colors/spacing (CSS variables only)
- 100% TypeScript coverage
- Passing test suite
- Lighthouse score >= 90
- No accessibility violations
## Detailed Batch Plan
[Include all batches from 2.2 with specific components listed]
## Timeline
Batch 1: Layout & Structure (Days 1-2)
Batch 2: Simple UI (Days 3-4)
[etc.]
## Notes and Considerations
[Any special requirements, blockers, or dependencies]
CRITICAL: Always use MCP for shadcn component discovery
Check if MCP server is accessible:
https://ui.shadcn.com/docs/mcpIf not available, install MCP server:
npx shadcn@latest mcp init --client claude
This enables:
Using MCP during development:
Run the initialization script:
bash ./scripts/init-nextjs-shadcn.sh [project-name]
Or manually initialize:
# Check Node.js version (18+ required)
node -v
# Create Next.js project with App Router
npx create-next-app@latest [project-name] \
--typescript \
--tailwind \
--app \
--src-dir \
--import-alias "@/*" \
--no-turbopack
cd [project-name]
# Initialize shadcn/ui
npx shadcn@latest init
# Configuration prompts:
# - TypeScript: Yes
# - Style: Default
# - Base color: Choose from slate/gray/zinc/neutral/stone
# - CSS variables: Yes (CRITICAL - required for theming)
# - Import alias: @/components
This creates:
components.json config filelib/utils.ts with cn() helpertailwind.config.ts with shadcn themeapp/globals.cssVERY IMPORTANT: All theming MUST use CSS variables
Color Format: OKLCH (Recommended)
This skill uses OKLCH (OKLab Lightness Chroma Hue) color space instead of HSL for better perceptual uniformity and color accuracy.
OKLCH Benefits:
Edit app/globals.css to define your design system:
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
:root {
--radius: 0.65rem;
/* Background - Pure white */
--background: 1 0 0;
--foreground: 0.141 0.005 285.823;
/* Card */
--card: 1 0 0;
--card-foreground: 0.141 0.005 285.823;
/* Popover */
--popover: 1 0 0;
--popover-foreground: 0.141 0.005 285.823;
/* Primary - Warm orange */
--primary: 0.646 0.222 41.116;
--primary-foreground: 0.98 0.016 73.684;
/* Secondary - Light purple-gray */
--secondary: 0.967 0.001 286.375;
--secondary-foreground: 0.21 0.006 285.885;
/* Muted - Subtle elements */
--muted: 0.967 0.001 286.375;
--muted-foreground: 0.552 0.016 285.938;
/* Accent */
--accent: 0.967 0.001 286.375;
--accent-foreground: 0.21 0.006 285.885;
/* Destructive - Red */
--destructive: 0.577 0.245 27.325;
/* Border and Input */
--border: 0.92 0.004 286.32;
--input: 0.92 0.004 286.32;
/* Focus ring */
--ring: 0.75 0.183 55.934;
/* Chart colors */
--chart-1: 0.837 0.128 66.29;
--chart-2: 0.705 0.213 47.604;
--chart-3: 0.646 0.222 41.116;
--chart-4: 0.553 0.195 38.402;
--chart-5: 0.47 0.157 37.304;
}
.dark {
/* Dark mode backgrounds */
--background: 0.141 0.005 285.823;
--foreground: 0.985 0 0;
/* Dark mode card */
--card: 0.21 0.006 285.885;
--card-foreground: 0.985 0 0;
/* Dark mode popover */
--popover: 0.21 0.006 285.885;
--popover-foreground: 0.985 0 0;
/* Dark mode primary - Brighter for contrast */
--primary: 0.705 0.213 47.604;
--primary-foreground: 0.98 0.016 73.684;
/* Dark mode secondary */
--secondary: 0.274 0.006 286.033;
--secondary-foreground: 0.985 0 0;
/* Dark mode muted */
--muted: 0.274 0.006 286.033;
--muted-foreground: 0.705 0.015 286.067;
/* Dark mode accent */
--accent: 0.274 0.006 286.033;
--accent-foreground: 0.985 0 0;
/* Dark mode destructive */
--destructive: 0.704 0.191 22.216;
/* Dark mode borders (with alpha) */
--border: 1 0 0 / 10%;
--input: 1 0 0 / 15%;
/* Dark mode focus ring */
--ring: 0.408 0.123 38.172;
/* Chart colors (consistent) */
--chart-1: 0.837 0.128 66.29;
--chart-2: 0.705 0.213 47.604;
--chart-3: 0.646 0.222 41.116;
--chart-4: 0.553 0.195 38.402;
--chart-5: 0.47 0.157 37.304;
}
}
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}
Customizing for Migrated Project:
If migrating an existing app with a design system, extract existing colors and map to CSS variables:
# Use the detection script to find existing colors
bash ./scripts/detect-hardcoded-values.sh /path/to/old/codebase
# Map old colors to new CSS variables (OKLCH format)
# Use https://oklch.com or https://colorjs.io to convert
# Example:
# Old: #FF6B35 (brand orange) โ --primary: 0.646 0.222 41.116
# Old: #3B82F6 (blue) โ --primary: 0.630 0.213 255.5
# Old: #10B981 (green) โ --success: 0.710 0.180 165.4
Use MCP to discover which components you need!
Install core components:
# Layout & Structure
npx shadcn@latest add card
npx shadcn@latest add separator
# Forms
npx shadcn@latest add button
npx shadcn@latest add input
npx shadcn@latest add label
npx shadcn@latest add select
npx shadcn@latest add checkbox
npx shadcn@latest add radio-group
npx shadcn@latest add form
# Navigation
npx shadcn@latest add navigation-menu
npx shadcn@latest add tabs
npx shadcn@latest add breadcrumb
# Feedback
npx shadcn@latest add alert
npx shadcn@latest add toast
npx shadcn@latest add dialog
npx shadcn@latest add tooltip
# Data Display
npx shadcn@latest add table
npx shadcn@latest add badge
npx shadcn@latest add avatar
# Overlays
npx shadcn@latest add popover
npx shadcn@latest add dropdown-menu
npx shadcn@latest add sheet
Query MCP for additional components as needed during development.
Install next-themes:
npm install next-themes
Create components/theme-provider.tsx:
"use client"
import * as React from "react"
import { ThemeProvider as NextThemesProvider } from "next-themes"
import { type ThemeProviderProps } from "next-themes/dist/types"
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
return <NextThemesProvider {...props}>{children}</NextThemesProvider>
}
Update app/layout.tsx:
import { ThemeProvider } from "@/components/theme-provider"
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" suppressHydrationWarning>
<body>
<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem
disableTransitionOnChange
>
{children}
</ThemeProvider>
</body>
</html>
)
}
Create components/example-card.tsx demonstrating best practices:
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
export function ExampleCard() {
return (
<Card className="w-full max-w-md">
<CardHeader>
<CardTitle>shadcn/ui Best Practices</CardTitle>
<CardDescription>
This card demonstrates proper shadcn patterns
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-sm text-muted-foreground">
Notice: No hardcoded colors, using CSS variables via Tailwind classes,
standard shadcn components, and proper typography scale.
</p>
</CardContent>
<CardFooter className="flex justify-between">
<Button variant="outline">Cancel</Button>
<Button>Continue</Button>
</CardFooter>
</Card>
)
}
Key Patterns Demonstrated:
text-muted-foreground)outline, default)For each batch of 5-10 components:
Step 1: Review Components in Batch
Load the component files and understand:
Step 2: Query MCP for shadcn Equivalents
Before converting, use MCP:
Step 3: Convert Component
Follow this pattern:
// OLD: Custom button with hardcoded styles
const CustomButton = ({ children, onClick, variant = 'primary' }) => {
const styles = {
primary: {
backgroundColor: '#3b82f6', // HARDCODED!
color: '#ffffff',
padding: '8px 16px', // HARDCODED!
borderRadius: '6px'
},
secondary: {
backgroundColor: '#6b7280',
color: '#ffffff',
padding: '8px 16px',
borderRadius: '6px'
}
}
return (
<button style={styles[variant]} onClick={onClick}>
{children}
</button>
)
}
// NEW: shadcn Button with CSS variables
import { Button } from "@/components/ui/button"
const CustomButton = ({ children, onClick, variant = 'default' }) => {
return (
<Button variant={variant} onClick={onClick}>
{children}
</Button>
)
}
Conversion Checklist:
Step 4: Replace Hardcoded Values with CSS Variables
// OLD: Hardcoded spacing and colors
<div style={{
backgroundColor: '#f3f4f6', // WRONG
padding: '20px', // WRONG
margin: '10px 0' // WRONG
}}>
// NEW: Tailwind classes using CSS variables
<div className="bg-secondary p-5 my-2.5">
// Or for custom spacing:
<div className="bg-secondary" style={{ padding: 'var(--spacing-5)' }}>
Step 5: Test Functionality
After converting each component:
# Run tests
npm test
# Visual testing
npm run dev
# Manually verify component renders correctly
Step 6: Verify No Violations
Run detection script on new components:
bash ./scripts/detect-hardcoded-values.sh src/components/[batch-name]
Should return 0 violations.
Step 7: Mark Batch Complete, Move to Next
Update todo list and migration-plan.md with progress.
Refer to ./references/shadcn-component-mapping.md for detailed mappings.
Quick reference:
| Pattern | Old Approach | shadcn Approach |
|---|---|---|
| Button | Custom styled button | <Button variant="..."> |
| Modal/Dialog | Custom overlay | <Dialog> with <DialogTrigger> and <DialogContent> |
| Form Input | Custom input with validation | <Form> + <FormField> + react-hook-form |
| Dropdown | Custom select | <Select> or <DropdownMenu> |
| Table | Custom table | <Table> or DataTable pattern |
| Tooltip | Custom hover component | <Tooltip> |
| Toast/Notification | Custom notification | useToast() hook + <Toaster> |
| Tabs | Custom tab component | <Tabs> with <TabsList> and <TabsContent> |
| Card | Custom card | <Card> with subcomponents |
| Badge | Custom badge/pill | <Badge variant="..."> |
For components without direct shadcn equivalents:
Option 1: Composition
Build using shadcn primitives:
// Complex dashboard widget using shadcn primitives
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { Badge } from "@/components/ui/badge"
export function DashboardWidget({ title, data, onRefresh }) {
return (
<Card>
<CardHeader className="flex flex-row items-center justify-between">
<CardTitle>{title}</CardTitle>
<Button variant="outline" size="sm" onClick={onRefresh}>
Refresh
</Button>
</CardHeader>
<CardContent>
{data.map(item => (
<div key={item.id} className="flex items-center justify-between py-2">
<span className="text-sm">{item.label}</span>
<Badge variant={item.status === 'success' ? 'default' : 'destructive'}>
{item.value}
</Badge>
</div>
))}
</CardContent>
</Card>
)
}
Option 2: Extend shadcn Components
Create custom components that extend shadcn:
// Custom component extending shadcn Button
import { Button } from "@/components/ui/button"
import { cn } from "@/lib/utils"
interface IconButtonProps extends React.ComponentProps<typeof Button> {
icon: React.ReactNode
}
export function IconButton({ icon, children, className, ...props }: IconButtonProps) {
return (
<Button className={cn("flex items-center gap-2", className)} {...props}>
{icon}
{children}
</Button>
)
}
Option 3: Use shadcn Blocks
Use MCP to discover shadcn blocks (pre-built complex components):
"What blocks are available in shadcn for [use case]?"
Install blocks:
npx shadcn@latest add [block-name]
Convert pages to Next.js App Router structure:
Old Structure (React Router):
src/
pages/
Home.tsx
About.tsx
Dashboard.tsx
users/
UserList.tsx
UserDetail.tsx
New Structure (Next.js App Router):
app/
page.tsx # Home
about/
page.tsx # About
dashboard/
page.tsx # Dashboard
layout.tsx # Dashboard layout
users/
page.tsx # UserList
[id]/
page.tsx # UserDetail
layout.tsx # Root layout
loading.tsx # Loading state
error.tsx # Error boundary
Example Conversion:
// OLD: React Router page
// src/pages/Dashboard.tsx
import { useNavigate } from 'react-router-dom'
export function Dashboard() {
const navigate = useNavigate()
return (
<div style={{ padding: '20px' }}>
<h1>Dashboard</h1>
<button onClick={() => navigate('/users')}>
View Users
</button>
</div>
)
}
// NEW: Next.js App Router page
// app/dashboard/page.tsx
import Link from 'next/link'
import { Button } from '@/components/ui/button'
export default function DashboardPage() {
return (
<div className="container py-6">
<h1 className="text-3xl font-bold mb-6">Dashboard</h1>
<Link href="/users">
<Button>View Users</Button>
</Link>
</div>
)
}
Key Changes:
<Link> instead of router navigationLoad reference: ./references/react-to-nextjs.md for state management patterns
Common patterns:
Local State (useState):
"use client"Global State:
Server State:
# Run all tests
npm test
# Run with coverage
npm test -- --coverage
# Ensure 100% of migrated components have passing tests
Manual verification checklist:
Optional: Set up automated visual regression testing with Percy, Chromatic, or Playwright.
Critical: Test on real devices, not just browser DevTools
Refer to: ./references/responsive-design-patterns.md for comprehensive responsive testing guidelines.
Device Testing Checklist:
Orientation Testing:
Responsive Patterns Verification:
Breakpoint Verification:
# Test all Tailwind breakpoints
# sm: 640px, md: 768px, lg: 1024px, xl: 1280px, 2xl: 1536px
# Verify components respond correctly at each breakpoint
Example Components:
Review ./assets/component-templates/ for responsive design examples:
responsive-navigation.tsx - Mobile/tablet/desktop navigation patternsresponsive-data-table.tsx - Responsive table with mobile cardsresponsive-dashboard.tsx - Responsive grid layoutscomplex-form.tsx - Multi-step responsive formbash ./scripts/detect-hardcoded-values.sh src/
Expected result: 0 violations
If violations found, return to Phase 4 and fix.
Critical: Achieve WCAG 2.1 Level AA compliance
Refer to: ./references/accessibility-best-practices.md for comprehensive accessibility testing guidelines.
# Install axe DevTools or use Lighthouse
npm install -D @axe-core/playwright
# Run accessibility tests
npm run test:a11y
shadcn/ui components are built with accessibility in mind (using Radix UI primitives), but verify:
Automated Testing:
Keyboard Navigation (WCAG 2.1.1, 2.1.2):
Screen Reader Testing: Test with real screen readers:
Screen Reader Checklist (WCAG 1.3.1, 4.1.2):
Color Contrast (WCAG 1.4.3):
Forms Accessibility (WCAG 3.3.1, 3.3.2):
Touch Targets (WCAG 2.5.5):
ARIA Usage (WCAG 4.1.2):
Complete WCAG 2.1 AA Checklist:
See ./references/accessibility-best-practices.md for full WCAG 2.1 Level AA checklist.
# Build for production
npm run build
# Analyze bundle
npm run analyze # If you have bundle analyzer configured
Run Lighthouse audit:
Performance Checklist:
Once migration is verified:
# Remove old framework code
rm -rf src/old-components/ # or whatever old structure was
# Remove old dependencies
npm uninstall [old-framework] [old-ui-library] styled-components emotion ...
# Clean up old config files
rm -f .babelrc webpack.config.js # etc.
Create migration-complete-report.md:
# Migration Completion Report
## Summary
Successfully migrated [Project Name] from [Old Framework] to Next.js + shadcn/ui.
## Statistics
- **Components Migrated**: 47
- **Lines of Code Changed**: ~5,200
- **Hardcoded Values Removed**: 231
- **CSS Variables Added**: 48
- **shadcn Components Used**: 18
## Test Results
- **Unit Tests**: 142/142 passing
- **Integration Tests**: 23/23 passing
- **Accessibility Score**: 98/100
- **Lighthouse Performance**: 94/100
## Before/After Comparison
### Before
- Framework: React 18 + Vite
- Styling: styled-components + custom CSS
- Hardcoded values: 231 violations
- Bundle size: 523 KB
- Lighthouse: 76
### After
- Framework: Next.js 15 + App Router
- Styling: Tailwind CSS + shadcn/ui
- Hardcoded values: 0 violations
- Bundle size: 398 KB (24% reduction)
- Lighthouse: 94 (23% improvement)
## Design System
All components now use CSS variables defined in globals.css:
- 24 color tokens
- 12 spacing tokens
- 8 typography tokens
- Full dark mode support
## Next Steps
- Deploy to production
- Monitor performance metrics
- Gather user feedback
- Optional: Implement additional shadcn blocks
1. CSS Variables for All Theming
globals.css2. Standard Components Only
3. Consistent Design Language
4. No Custom UI Components
5. Accessibility First
NEVER DO THESE:
โ Hardcoded Colors
// WRONG
<div style={{ backgroundColor: '#3b82f6' }}>
// RIGHT
<div className="bg-primary">
โ Hardcoded Spacing
// WRONG
<div style={{ padding: '20px', margin: '10px' }}>
// RIGHT
<div className="p-5 m-2.5">
โ Custom Styled Components for UI Primitives
// WRONG
const CustomButton = styled.button`
background: #3b82f6;
padding: 8px 16px;
border-radius: 6px;
`
// RIGHT
import { Button } from '@/components/ui/button'
โ Inline Styles
// WRONG
<div style={{ color: 'red', fontSize: '14px' }}>
// RIGHT
<div className="text-destructive text-sm">
โ Hardcoded Fonts
// WRONG
<h1 style={{ fontFamily: 'Montserrat' }}>
// RIGHT
<h1 className="font-sans text-4xl font-bold">
โ Emoji Icons (use Lucide React icons instead)
// WRONG
<span>โ Delete</span>
// RIGHT
import { X } from 'lucide-react'
<Button variant="destructive">
<X className="mr-2 h-4 w-4" />
Delete
</Button>
โ Arbitrary CSS Values
// WRONG
<div className="text-[#ff0000]">
// RIGHT
<div className="text-destructive">
โ Use Semantic Color Names
// Use semantic CSS variable names
bg-background
text-foreground
bg-primary
text-primary-foreground
bg-secondary
text-muted-foreground
border-border
โ Use Tailwind Spacing Scale
// Consistent spacing using Tailwind
p-2, p-4, p-6, p-8 // padding
m-2, m-4, m-6, m-8 // margin
gap-2, gap-4 // flex/grid gap
โ Compose Components
// Build complex UIs by composing shadcn components
import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card'
import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'
โ Use MCP for Discovery
// Before building, ask MCP:
// "What shadcn component should I use for [use case]?"
// "Show me examples of shadcn [component]"
โ Extend via Composition
// Create higher-level components that compose shadcn
export function FeatureCard({ feature }: { feature: Feature }) {
return (
<Card>
<CardHeader>
<CardTitle>{feature.title}</CardTitle>
</CardHeader>
<CardContent>
<p className="text-muted-foreground">{feature.description}</p>
<Button className="mt-4">Learn More</Button>
</CardContent>
</Card>
)
}
Framework-Specific Migration:
Component & Styling:
Responsive Design & Accessibility:
Example Component Templates:
Scripts:
./scripts/analyze-codebase.py - Automated codebase analysis./scripts/detect-hardcoded-values.sh - Find anti-patterns./scripts/init-nextjs-shadcn.sh - Project initialization./scripts/generate-migration-report.py - Create migration reportOfficial Documentation:
If creating a new Next.js app (not migrating):
Initialize
bash ./scripts/init-nextjs-shadcn.sh my-app
Check MCP Access
npx shadcn@latest mcp init --client claude
Install Components
npx shadcn@latest add [component]Build with Best Practices
This skill enables systematic frontend migration to Next.js + shadcn/ui with strict adherence to design principles:
Result: Production-grade Next.js applications following shadcn/ui best practices with consistent design systems, full dark mode support, and no anti-patterns.