Awesome-omni-skill nextjs-shadcn-builder
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.
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/nextjs-shadcn-builder-mikisbell" ~/.claude/skills/diegosouzapw-awesome-omni-skill-nextjs-shadcn-builder-5ff975 && rm -rf "$T"
skills/development/nextjs-shadcn-builder-mikisbell/SKILL.mdNext.js + shadcn/ui Builder & Migration Tool
Build production-grade Next.js applications or systematically migrate existing frontends to Next.js + shadcn/ui following strict design principles and best practices.
Overview
This skill handles two primary workflows:
- Creating New Next.js Applications - Initialize projects with Next.js 15+ (App Router), shadcn/ui, and proper design system setup
- Migrating Existing Frontends - Analyze any frontend codebase (React, Vue, Angular, vanilla JS) and systematically convert to Next.js + shadcn/ui
Core Philosophy: 100% adherence to shadcn/ui design principles:
- CSS variables for all theming (colors, spacing, typography)
- Standard shadcn/ui components only (no custom UI components)
- No hardcoded values (colors, spacing, fonts)
- Consistent design tokens across the application
- Mobile-first responsive design for all devices (phone, tablet, desktop)
- WCAG 2.1 Level AA accessibility compliance
- Best practices from https://ui.shadcn.com
Workflow Decision Tree
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
High-Level Workflow for Migration
Phase 1: Codebase Analysis
Automated analysis of existing frontend to understand scope and complexity.
Steps:
- Framework and version detection
- Component inventory and categorization
- Hardcoded value detection (colors, spacing, custom components)
- Styling approach analysis (CSS, SCSS, CSS-in-JS, Tailwind, etc.)
- State management and routing pattern identification
- Generate comprehensive analysis report
Deliverables:
- Framework analysis report
- Component inventory (JSON)
- Hardcoded values report
- Complexity assessment
Phase 2: Migration Planning
Create systematic conversion plan with prioritized batches.
Steps:
- Map existing components to shadcn/ui equivalents
- Identify components requiring custom development
- Organize conversion into batches (5-10 components per batch)
- Assess risk and complexity per batch
- Create detailed migration plan
Deliverables:
- Component mapping table
- Batched conversion plan
- Risk assessment
- Estimated complexity per component
Phase 3: Next.js + shadcn Setup
Initialize Next.js infrastructure alongside or replacing existing codebase.
Steps:
- Check/install shadcn MCP server for documentation access
- Initialize Next.js 15+ with App Router and TypeScript
- Install and configure Tailwind CSS
- Run shadcn/ui initialization
- Set up CSS variables and design tokens
- Configure path aliases (@/)
- Install essential shadcn components
- Create design system documentation
Deliverables:
- Configured Next.js project
- Design token system (CSS variables)
- Component library setup
- Path aliases configured
Phase 4: Systematic Conversion
Convert components batch by batch with testing after each batch.
Steps:
- Batch 1: Layout & Structure (Header, Footer, Layout wrappers)
- Batch 2: Simple UI Components (Buttons, Cards, Badges, Alerts)
- Batch 3: Form Components (Inputs, Selects, Checkboxes, Forms)
- Batch 4: Complex Components (Tables, Dialogs, Command Menus, Data visualizations)
- Batch 5: Styling Standardization (Remove hardcoded values, apply CSS variables)
- Batch 6: Pages & Routes (Convert pages, set up Next.js routing)
Per Batch Workflow:
- Select 5-10 related components
- Use MCP to find appropriate shadcn components
- Convert components following shadcn patterns
- Replace hardcoded values with CSS variables
- Test functionality
- Verify visual consistency
- Move to next batch
Deliverables:
- Migrated components (batch by batch)
- Updated styling with CSS variables
- Next.js App Router pages
- Passing tests per batch
Phase 5: Verification & Cleanup
Final testing, optimization, and old code removal.
Steps:
- Run full test suite
- Visual regression testing
- Responsive design testing (mobile, tablet, desktop)
- Performance audit
- Accessibility audit (WCAG 2.1 Level AA compliance)
- Remove old framework code
- Documentation updates
- Generate completion report
Deliverables:
- Test results
- Responsive design verification report
- Performance metrics
- Accessibility audit report (WCAG 2.1 AA)
- Clean codebase
- Migration summary
Phase 1: Codebase Analysis (Detailed Instructions)
1.1 Framework Detection
Run the automated analysis script:
python ./scripts/analyze-codebase.py /path/to/existing/codebase
This script will:
- Detect framework (React, Vue, Angular, Svelte, vanilla JS, etc.)
- Identify framework version
- Detect build tool (Vite, Webpack, Parcel, etc.)
- Find package.json dependencies
- Map directory structure
Output:
codebase-analysis.json with framework metadata
1.2 Component Inventory
The analysis script automatically generates a component inventory including:
- Component name and file path
- Component type (functional, class, Vue SFC, etc.)
- Props/inputs
- State usage
- Child components
- External dependencies
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"] } ] }
1.3 Hardcoded Value Detection
Run the detection script:
bash ./scripts/detect-hardcoded-values.sh /path/to/existing/codebase
This script detects:
- Hardcoded colors:
,#hex
,rgb()
,rgba()
, color nameshsl() - Inline spacing:
,margin: 20pxpadding: 1rem - Custom font declarations: non-standard fonts
- Magic numbers: arbitrary values in components
- Inline styles:
style={{...}} - Non-standard patterns: CSS-in-JS, styled-components that should be Tailwind
Output:
hardcoded-values-report.md with violations grouped by category
1.4 Generate Analysis Report
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
Phase 2: Migration Planning (Detailed Instructions)
2.1 Component Mapping Strategy
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:
- "What shadcn components are available for buttons?"
- "Show me form components in shadcn"
- "What's the shadcn equivalent of a modal/dialog?"
- "Available data display components in shadcn"
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:
- For React: Read
./references/react-to-nextjs.md - For Vue: Read
./references/vue-to-nextjs.md - For Angular: Read
./references/angular-to-nextjs.md - For styling: Read
./references/styling-migration.md
2.2 Batch Organization
Organize components into batches following these principles:
Batching Strategy:
- Group by type (layout, forms, data display, navigation)
- Simple to complex (start with easy wins)
- Dependency order (convert dependencies first)
- Batch size: 5-10 components per batch
Example Batch Plan:
Batch 1: Layout & Structure (Priority: Critical)
- Header
- Footer
- MainLayout
- Container
- Sidebar
Batch 2: Simple UI Components (Priority: High)
- Button → shadcn Button
- Card → shadcn Card
- Badge → shadcn Badge
- Alert → shadcn Alert
- Avatar → shadcn Avatar
Batch 3: Form Components (Priority: High)
- Input → shadcn Input
- Select → shadcn Select
- Checkbox → shadcn Checkbox
- RadioGroup → shadcn RadioGroup
- Form validation → shadcn Form + react-hook-form
Batch 4: Navigation (Priority: Medium)
- NavBar → shadcn NavigationMenu
- Breadcrumbs → shadcn Breadcrumb
- Tabs → shadcn Tabs
- Pagination → shadcn Pagination
Batch 5: Data Display (Priority: Medium)
- Table → shadcn Table
- DataGrid → shadcn DataTable (with sorting, filtering)
- List → shadcn custom composition
- Accordion → shadcn Accordion
Batch 6: Overlays & Modals (Priority: Medium)
- Modal → shadcn Dialog
- Tooltip → shadcn Tooltip
- Popover → shadcn Popover
- DropdownMenu → shadcn DropdownMenu
Batch 7: Complex Components (Priority: Low)
- Charts → shadcn Charts (Recharts integration)
- Calendar/DatePicker → shadcn Calendar
- CommandPalette → shadcn Command
- DataVisualization → Custom with shadcn primitives
Batch 8: Styling Standardization (Priority: Critical)
- Extract all hardcoded colors → CSS variables
- Convert spacing to Tailwind classes
- Standardize typography
- Apply theme system consistently
Batch 9: Pages & Routing (Priority: Critical)
- Convert pages to Next.js App Router
- Set up layouts with Next.js layout.tsx
- Implement routing patterns
- Add loading and error states
2.3 Risk Assessment
For each batch, identify risks:
- API Differences: Components with significantly different APIs
- Missing Features: Features in old components not in shadcn
- State Management: Complex state that needs refactoring
- Dependencies: External libraries that need replacement
- Custom Logic: Business logic tightly coupled to UI
Risk Mitigation:
- Document API differences before conversion
- Create adapter/wrapper components when needed
- Write tests before migration
- Keep old components temporarily during transition
2.4 Create Detailed Migration Plan
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]
Phase 3: Next.js + shadcn Setup (Detailed Instructions)
3.1 Check/Install shadcn MCP Server
CRITICAL: Always use MCP for shadcn component discovery
-
Check if MCP server is accessible:
- Try to access documentation at
https://ui.shadcn.com/docs/mcp - Check if you can query shadcn components via MCP
- Try to access documentation at
-
If not available, install MCP server:
npx shadcn@latest mcp init --client claude
This enables:
- Real-time shadcn documentation access
- Component discovery and search
- Block and chart template discovery
- Theme and design token reference
Using MCP during development:
- "What components are available for [use case]?"
- "Show me the props for shadcn Button"
- "Available chart types in shadcn"
- "How to use shadcn Form with validation"
3.2 Initialize Next.js Project
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]
3.3 Install and Configure shadcn/ui
# 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:
config filecomponents.json
with cn() helperlib/utils.ts- Updated
with shadcn themetailwind.config.ts - CSS variables in
app/globals.css
3.4 Configure Design Tokens (CSS Variables)
VERY 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:
- Perceptually uniform (equal changes = equal perceived differences)
- Better gradient interpolation
- More predictable lightness
- Better for accessibility (more accurate contrast ratios)
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
3.5 Install Essential shadcn Components
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.
3.6 Set Up Theme Provider (Dark Mode Support)
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> ) }
3.7 Create Example Component
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:
- Uses standard shadcn components (Card, Button)
- No hardcoded colors (uses
)text-muted-foreground - CSS variables automatically applied via Tailwind
- Semantic variants (
, default)outline - Proper component composition
Phase 4: Systematic Conversion (Detailed Instructions)
4.1 Component Conversion Workflow
For each batch of 5-10 components:
Step 1: Review Components in Batch
Load the component files and understand:
- Current functionality
- Props/API
- Styling approach
- State management
- Event handlers
Step 2: Query MCP for shadcn Equivalents
Before converting, use MCP:
- "What's the shadcn component for [component type]?"
- "Show me shadcn [component] props and examples"
- "How to use shadcn [component] with [feature]?"
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:
- ✅ Replace with shadcn component
- ✅ Remove all hardcoded colors
- ✅ Remove inline styles
- ✅ Use Tailwind classes only
- ✅ Use semantic variants (default, outline, destructive, etc.)
- ✅ Preserve all functionality
- ✅ TypeScript types properly defined
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.
4.2 Common Component Migrations
Refer to
for detailed mappings../references/shadcn-component-mapping.md
Quick reference:
| Pattern | Old Approach | shadcn Approach |
|---|---|---|
| Button | Custom styled button | |
| Modal/Dialog | Custom overlay | with and |
| Form Input | Custom input with validation | + + react-hook-form |
| Dropdown | Custom select | or |
| Table | Custom table | or DataTable pattern |
| Tooltip | Custom hover component | |
| Toast/Notification | Custom notification | hook + |
| Tabs | Custom tab component | with and |
| Card | Custom card | with subcomponents |
| Badge | Custom badge/pill | |
4.3 Handling Complex Components
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]
4.4 Page and Route Conversion
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:
- Default export for pages
- Use Next.js
instead of router navigation<Link> - Remove hardcoded padding → Tailwind classes
- Use shadcn Button
4.5 State Management Migration
Load reference:
./references/react-to-nextjs.md for state management patterns
Common patterns:
Local State (useState):
- Remains the same in Next.js App Router
- Mark client components with
"use client"
Global State:
- Redux → Zustand or React Context
- MobX → Zustand
- Recoil → Zustand or Jotai
Server State:
- React Query → TanStack Query (still works in Next.js)
- SWR → SWR (Next.js compatible)
- Or use Next.js Server Components for server data
Phase 5: Verification & Cleanup (Detailed Instructions)
5.1 Run Test Suite
# Run all tests npm test # Run with coverage npm test -- --coverage # Ensure 100% of migrated components have passing tests
5.2 Visual Regression Testing
Manual verification checklist:
- All pages render correctly
- All components match design system
- Dark mode works correctly
- Responsive design maintained
- No hardcoded colors visible
- Consistent spacing throughout
- Typography follows design system
Optional: Set up automated visual regression testing with Percy, Chromatic, or Playwright.
5.3 Responsive Design Testing
Critical: Test on real devices, not just browser DevTools
Refer to:
./references/responsive-design-patterns.md for comprehensive responsive testing guidelines.
Device Testing Checklist:
- iPhone SE (320px - smallest modern viewport)
- iPhone 14 Pro (390px)
- iPad (768px)
- iPad Pro (1024px)
- Desktop (1280px - 1920px)
- Ultrawide (2560px+)
Orientation Testing:
- Portrait mode on mobile/tablet
- Landscape mode on mobile/tablet
- Responsive behavior when rotating device
Responsive Patterns Verification:
- Navigation: Mobile hamburger → tablet sidebar → desktop navbar
- Data tables: Mobile cards → tablet scrollable → desktop full table
- Grids: 1 col mobile → 2 cols tablet → 3-4 cols desktop
- Forms: Single column mobile → multi-column desktop
- Touch targets: Minimum 44x44px on mobile
- Typography: Readable at all screen sizes (minimum 16px body text)
- Images: Responsive sizing with proper aspect ratios
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:
- Mobile/tablet/desktop navigation patternsresponsive-navigation.tsx
- Responsive table with mobile cardsresponsive-data-table.tsx
- Responsive grid layoutsresponsive-dashboard.tsx
- Multi-step responsive formcomplex-form.tsx
5.4 Run Final Hardcoded Values Check
bash ./scripts/detect-hardcoded-values.sh src/
Expected result: 0 violations
If violations found, return to Phase 4 and fix.
5.5 Accessibility Audit (WCAG 2.1 Level AA)
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:
- Run axe DevTools browser extension on all pages
- Lighthouse accessibility score >= 90
- No WCAG violations reported by automated tools
- eslint-plugin-jsx-a11y passing (if configured)
Keyboard Navigation (WCAG 2.1.1, 2.1.2):
- All interactive elements accessible via Tab
- Logical tab order (follows visual layout)
- No keyboard traps (can Tab out of all components)
- Enter/Space activates buttons/links
- Escape closes modals/dialogs
- Arrow keys navigate within components (tabs, menus, radio groups)
- Focus indicators visible on all interactive elements
Screen Reader Testing: Test with real screen readers:
- macOS: VoiceOver (Cmd + F5)
- Windows: NVDA (free) or JAWS
- Mobile: VoiceOver (iOS) or TalkBack (Android)
Screen Reader Checklist (WCAG 1.3.1, 4.1.2):
- All images have alt text
- Form inputs have associated labels
- Buttons have descriptive text or aria-label
- Headings follow logical hierarchy (h1 → h2 → h3)
- Landmarks present (header, nav, main, aside, footer)
- Dynamic content announces via aria-live regions
- Error messages announced to screen readers
Color Contrast (WCAG 1.4.3):
- Body text: Minimum 4.5:1 contrast ratio
- Large text (18pt+): Minimum 3:1 contrast ratio
- UI components: Minimum 3:1 contrast ratio
- Focus indicators: Minimum 3:1 contrast ratio
- Test both light and dark modes
Forms Accessibility (WCAG 3.3.1, 3.3.2):
- All inputs have visible labels
- Required fields clearly indicated
- Error messages specific and helpful
- Error messages associated with inputs (aria-describedby)
- Form validation doesn't rely on color alone
Touch Targets (WCAG 2.5.5):
- Minimum 44x44 CSS pixels for all touch targets on mobile
- Adequate spacing between touch targets (8px minimum)
ARIA Usage (WCAG 4.1.2):
- ARIA labels for icon-only buttons
- aria-expanded for collapsible sections
- aria-selected for tabs
- aria-hidden for decorative elements
- role="alert" for error messages
- role="status" for non-critical updates
Complete WCAG 2.1 AA Checklist: See
./references/accessibility-best-practices.md for full WCAG 2.1 Level AA checklist.
5.6 Performance Audit
# Build for production npm run build # Analyze bundle npm run analyze # If you have bundle analyzer configured
Run Lighthouse audit:
- Performance >= 90
- Accessibility >= 90
- Best Practices >= 90
- SEO >= 90
Performance Checklist:
- Core Web Vitals meet "Good" thresholds
- LCP (Largest Contentful Paint) < 2.5s
- FID (First Input Delay) < 100ms
- CLS (Cumulative Layout Shift) < 0.1
- Images optimized (using Next.js Image component)
- Code splitting implemented for large components
- Lazy loading below-the-fold content
- Bundle size reasonable (check with bundle analyzer)
5.7 Remove Old Code
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.
5.8 Generate Completion Report
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
shadcn Design Principles (CRITICAL)
Core Principles
1. CSS Variables for All Theming
- NEVER hardcode colors, spacing, or typography
- Define all design tokens as CSS variables in
globals.css - Use Tailwind classes that reference these variables
2. Standard Components Only
- Use shadcn/ui components as-is
- Extend via composition, not modification
- If shadcn doesn't have it, build with shadcn primitives
3. Consistent Design Language
- Follow shadcn's design patterns
- Use semantic variants (default, outline, destructive, ghost, link, secondary)
- Maintain consistent spacing scale
- Typography hierarchy from shadcn
4. No Custom UI Components
- Don't create custom buttons, inputs, cards, etc.
- Use shadcn components or build with shadcn primitives
- Exception: Business logic components (not UI primitives)
5. Accessibility First
- shadcn uses Radix UI (accessible by default)
- Don't override accessibility features
- Test with keyboard navigation and screen readers
Anti-Patterns to Avoid
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">
Best Practices
✅ 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> ) }
Reference Files
Framework-Specific Migration:
Component & Styling:
Responsive Design & Accessibility:
Example Component Templates:
- Responsive Navigation - Mobile/tablet/desktop navigation patterns ⭐ NEW
- Responsive Data Table - Card view on mobile, table on desktop ⭐ NEW
- Responsive Dashboard - Responsive grid layouts with stats and charts ⭐ NEW
- Complex Multi-Step Form - Form validation, file uploads, conditional fields ⭐ NEW
- Feature Card Example - Basic shadcn component composition
- User Profile Example - Avatar, badges, and layout patterns
Scripts:
- Automated codebase analysis./scripts/analyze-codebase.py
- Find anti-patterns./scripts/detect-hardcoded-values.sh
- Project initialization./scripts/init-nextjs-shadcn.sh
- Create migration report./scripts/generate-migration-report.py
Official Documentation:
- shadcn/ui: https://ui.shadcn.com
- Next.js: https://nextjs.org/docs
- Tailwind CSS: https://tailwindcss.com/docs
- Radix UI: https://www.radix-ui.com
- WCAG 2.1 Guidelines: https://www.w3.org/WAI/WCAG21/quickref/
Quick Start for New Projects
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
- Use MCP to discover needed components
- Install with
npx shadcn@latest add [component]
-
Build with Best Practices
- Use CSS variables only
- Compose shadcn components
- Follow design principles above
Summary
This skill enables systematic frontend migration to Next.js + shadcn/ui with strict adherence to design principles:
- Automated analysis of existing codebases
- Systematic batch conversion (5-10 components at a time)
- Zero tolerance for hardcoded values (CSS variables only)
- MCP integration for shadcn component discovery
- Multi-framework support (React, Vue, Angular, vanilla JS)
- Comprehensive verification (tests, accessibility, performance)
Result: Production-grade Next.js applications following shadcn/ui best practices with consistent design systems, full dark mode support, and no anti-patterns.