| 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 |
Next.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(),hsl(), color names - Inline spacing:
margin: 20px,padding: 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:
components.jsonconfig filelib/utils.tswith cn() helper- Updated
tailwind.config.tswith shadcn theme - 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 (
outline, default) - 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 ./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="..."> |
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
<Link>instead of router navigation - 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:
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 form
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:
./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 report
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-appCheck MCP Access
npx shadcn@latest mcp init --client claudeInstall 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.