21st-dev-builder-v2
21st.dev Web Builder v2
Build production-ready websites using 21st.dev — the largest open-source registry of React UI components. You are an expert at discovering, analyzing, selecting, and integrating 21st.dev components to create polished, cohesive web applications.
This skill makes you exceptionally good at:
- Live discovery — Always fetching the latest components from 21st.dev before building
- Smart analysis — Evaluating which components best fit the user's needs
- Design coherence — Maintaining visual consistency across components from different authors
- Full-stack composition — Building complete multi-page applications, not just isolated pages
Core Knowledge
What is 21st.dev?
An open-source community registry (the "npm for design engineers") with 1400+ React components. Unlike npm packages, components are installed as full source code you own and can customize. Built on shadcn/ui philosophy.
Tech Stack
- Framework: React 18+ / Next.js (App Router preferred)
- Styling: Tailwind CSS 4+
- Primitives: Radix UI
- Language: TypeScript
- Install:
npx shadcn@latest add "https://21st.dev/r/{author}/{component}"
URL Patterns
| Purpose | URL Pattern |
|---|---|
| Browse category | https://21st.dev/s/{slug} |
| Component detail | https://21st.dev/r/{author}/{component} |
| Author profile | https://21st.dev/{author} |
| Community search | https://21st.dev/community/components/search |
Workflow
Phase 1: Project Setup
Check if the project is ready. Look for package.json, tailwind.config.*, and components.json.
New project:
npx create-next-app@latest my-app --typescript --tailwind --eslint --app --src-dir --import-alias "@/*"
cd my-app
npx shadcn@latest init -d
Existing project missing shadcn:
npx shadcn@latest init
Check MCP availability: If 21st_magic_component_builder tool is available, use it as the primary component generation method. Otherwise, use WebSearch + WebFetch + npx install (works perfectly well).
Phase 2: Requirement Analysis
Break down the user's request into a component plan:
- Identify the application type — What kind of app or page is being built?
- List required sections/features — What does each page need?
- Map to component categories — Use the Component Map below
- Identify shared components — Which components appear across multiple pages?
Component Map
| Building... | Search these categories on 21st.dev |
|---|---|
| Landing page | hero, features, pricing, testimonials, cta, footers, navbars, backgrounds, announcements, clients |
| Dashboard | sidebar, cards, tables, tabs, buttons, menus, badges, numbers |
| Auth pages | sign-ins, sign-ups, forms, inputs, buttons |
| Blog / Content | cards, texts, images, paginations, scroll-areas |
| E-commerce | cards, carousels, badges, buttons, dialogs, inputs, tabs, selects |
| Form-heavy app | inputs, selects, checkboxes, radio-groups, date-pickers, forms, text-areas, toggles |
| AI / Chat app | ai-chats, inputs, buttons, cards, spinner-loaders |
| Settings page | forms, inputs, toggles, tabs, selects, checkboxes, accordions |
| Portfolio | hero, cards, images, texts, scroll-areas, backgrounds, navigation-menus |
| SaaS product | hero, pricing, features, testimonials, navbars, footers, cta, comparisons |
Phase 3: Live Component Discovery
Every build session must include live discovery. 21st.dev adds new components constantly — never rely on memory alone.
Discovery Strategy
For each component category you need, follow this search sequence:
Step 1: Browse the category page
WebFetch: https://21st.dev/s/{category-slug}
This shows all available components in that category with names, authors, and popularity.
Step 2: Deep-dive on promising components
WebFetch: https://21st.dev/r/{author}/{component}
View the component's demo, code, dependencies, and installation command.
Step 3: Search for specific styles (if category browsing isn't enough)
WebSearch: "site:21st.dev {specific style or feature}"
Example: site:21st.dev animated gradient hero or site:21st.dev glassmorphism card
Category Slugs Reference
Read references/component-catalog.md for the full catalog of categories with slugs, counts, and top authors. Here are the most-used ones:
Landing Sections: hero, features, pricing, testimonials, cta, footers, navbars, backgrounds, announcements, clients, comparisons, docks, shaders
UI Components: buttons, inputs, cards, selects, sliders, accordions, tabs, dialogs, calendars, ai-chats, tables, badges, dropdowns, alerts, forms, popovers, text-areas, radio-groups, spinner-loaders, paginations, checkboxes, menus, numbers, avatars, carousels, links, toggles, date-pickers, tooltips, toasts, sidebar, sign-ins, sign-ups, file-uploads, file-trees, icons, tags, notifications, empty-states
Phase 4: Component Analysis & Selection
This is where expertise matters most. For each component slot, evaluate candidates on these dimensions:
Selection Criteria (in priority order)
- Functional fit — Does it actually do what's needed? Check props, interactivity, responsiveness.
- Visual quality — Is it polished, modern, and well-designed? Check the live preview.
- Design coherence — Will it look consistent with other selected components? Prefer:
- Same author for related components (e.g., all navbar + footer from one author)
- Similar design language (rounded vs. sharp corners, shadow style, spacing)
- Consistent color system (CSS variable-based components work best together)
- Completeness — Does it support dark mode? Is it responsive? Accessible?
- Popularity — Higher likes/downloads usually mean better quality and fewer bugs.
- Recency — Recently updated components often use newer patterns and APIs.
- Dependencies — Fewer external dependencies = easier integration.
Decision Framework
For each component slot:
1. Find 2-3 candidates from category browsing
2. Score each on the criteria above (mentally)
3. If user is involved → present top 2 with preview links + your recommendation
4. If user says "you decide" → pick the best-scoring one
5. Document your choice with reasoning
Author Consistency Strategy
When building a full page or site, try to use components from a small set of authors. This dramatically improves visual coherence. Notable authors with broad component ranges:
- shadcn — The foundation. Clean, minimal, highly composable.
- bundui — Animated, modern components.
- magicui — Motion-rich, creative components.
- Other prolific authors can be discovered during live browsing.
Phase 4.5: Build vs Install Decision
Not every section needs a 21st.dev component. For each section, decide:
INSTALL from 21st.dev when:
- The section needs complex interactivity (navbar with dropdowns, pricing toggle, carousel)
- The section needs polished animations you don't want to write (animated hero, testimonial slider)
- A 21st.dev component fits the need almost perfectly
WRITE CUSTOM when:
- The section is simple (feature grid, stats row, basic CTA)
- No good 21st.dev component exists for this exact need
- You need very specific layout that would require heavy modification anyway
- Mixing too many authors would break design coherence
A typical landing page might install 2-3 complex components (hero, navbar, footer) and write 2-3 simple sections (features grid, stats, CTA) custom. This is faster and produces better results than forcing every section through 21st.dev.
Phase 5: Installation & Integration
Install components:
npx shadcn@latest add "https://21st.dev/r/{author}/{component-name}"
What this does:
- Copies component source code to your project (usually
components/ui/orcomponents/blocks/) - Installs required npm dependencies
- Updates Tailwind config if needed
- Resolves internal component dependencies
Installation order matters:
- Install base/primitive components first (buttons, inputs)
- Then composite components that may depend on them (forms, dialogs)
- Finally section-level components (hero, pricing)
Post-Install Compatibility Fixes (CRITICAL)
After installing each component, immediately check for these common issues before moving on:
1. render prop vs asChild conflict:
Many newer 21st.dev components use render prop from @base-ui/react, but your project may use standard shadcn asChild. If you see TypeScript errors about render prop:
// BROKEN: Component uses render prop
<Button render={<a href="/signup" />}>Sign Up</Button>
// FIX: Convert to asChild pattern
<Button asChild><a href="/signup">Sign Up</a></Button>
Check Button, SheetTrigger, SelectTrigger in every installed component.
2. Container width mismatch: Components may assume different max-widths. After installing, verify each component uses a consistent container:
// If component uses its own container, it may conflict with your layout
// Wrap all sections in a consistent container OR
// Remove the component's internal container and use your own
<section className="py-20">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
{/* component content here */}
</div>
</section>
3. Missing CSS variables:
If a component looks invisible or wrong, check that your globals.css defines all required CSS variables. Common missing ones: --border, --ring, --muted, --muted-foreground, --accent, --accent-foreground.
4. framer-motion typing issues:
Some components use ease arrays that TypeScript rejects. Fix by casting:
// BROKEN
ease: [0.16, 1, 0.3, 1]
// FIX
ease: [0.16, 1, 0.3, 1] as const
5. Faint/invisible card backgrounds:
Many 21st.dev testimonial and feature cards use extremely subtle gradients (from-muted/50 to-muted/10 or border-t only) that appear invisible on white backgrounds, especially in marquees where edge fades add further transparency. Fix by giving cards visible styling:
// BROKEN: Nearly invisible
"rounded-lg border-t bg-gradient-to-b from-muted/50 to-muted/10"
// FIX: Clearly visible with depth
"rounded-xl border border-border/60 bg-card shadow-sm"
6. Edge fade gradients too aggressive on marquees:
Marquee components often have w-1/3 fade gradients on each side, covering 2/3 of the content area. Reduce to w-1/6 so cards remain visible:
// BROKEN: Covers too much
"absolute inset-y-0 left-0 w-1/3 bg-gradient-to-r from-background"
// FIX: Subtle fade
"absolute inset-y-0 left-0 w-1/6 bg-gradient-to-r from-background"
7. Gradient colors with oklch():
Tailwind v4 uses oklch() for color values, but oklch is poorly rendered in radial-gradient() and some gradient contexts. Use rgba() or hex values for custom gradients:
// BROKEN: oklch in gradients renders poorly
"bg-[radial-gradient(ellipse_at_center,_oklch(0.55_0.28_285_/_0.18)_0%,_transparent_65%)]"
// FIX: Use rgba for reliable gradient rendering
"bg-[radial-gradient(ellipse_at_center,_rgba(139,92,246,0.18)_0%,_transparent_65%)]"
8. Gradient backgrounds behind parent backgrounds (z-index trap):
Don't put gradient decorative elements with -z-10 behind a parent that has its own bg-background. The parent's opaque background covers the gradient. Instead, apply the gradient directly on the section:
// BROKEN: Gradient div behind parent bg-background
<section className="bg-background">
<div className="-z-10 bg-gradient-to-b ..."> {/* invisible! */}
// FIX: Apply gradient directly on the section
<section className="bg-gradient-to-b from-[#ede9fe] via-[#f5f3ff] to-white">
If installation fails:
- Check error message — usually a missing peer dependency
- Try
npm install {missing-dep}then retry - If component URL is wrong, search 21st.dev for the correct path
- Last resort: fetch the component code via WebFetch and create files manually
Phase 6: Page Composition
Layout Normalization (DO THIS FIRST)
Before composing, normalize the layout of all installed components so they play well together. 21st.dev components from different authors often have conflicting container widths, padding, and alignment. Fix this upfront:
- Pick one container width for the entire page:
max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 - Open each installed component file and check if it has its own container/max-width
- Either: remove the component's internal container and wrap it externally, or ensure it matches your chosen width
- Check text alignment: some components center-align content, others left-align. Normalize.
- Check hero height: hero components often use
min-h-screenwhich may be too tall. Adjust tomin-h-[80vh]or less if needed.
Composition Patterns
Landing Page:
<Navbar /> {/* sticky top-0 z-50 */}
<main>
<Hero /> {/* min-h-[80vh] — NOT min-h-screen */}
<Features /> {/* py-20 bg-muted/50 */}
<SocialProof /> {/* py-16 */}
<Pricing /> {/* py-20 bg-muted/50 */}
<Testimonials /> {/* py-16 */}
<CTA /> {/* py-20 bg-primary text-primary-foreground */}
</main>
<Footer />
Dashboard:
<SidebarProvider>
<Sidebar>{/* navigation items */}</Sidebar>
<main className="flex-1">
<header>{/* toolbar, breadcrumbs */}</header>
<div className="p-6">
<div className="grid gap-4 md:grid-cols-3">{/* stat cards */}</div>
<div className="mt-6">{/* data table or content */}</div>
</div>
</main>
</SidebarProvider>
Auth Flow:
<div className="min-h-screen flex items-center justify-center bg-muted/30">
<div className="w-full max-w-md">
<SignInCard /> {/* or SignUpCard */}
</div>
</div>
Multi-page App Layout:
// app/layout.tsx
<html>
<body>
<Navbar />
{children}
<Footer />
</body>
</html>
Spacing & Layout Rules
- Sections:
py-16 md:py-20 lg:py-24(responsive vertical padding) - Content width:
max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 - Card grids:
grid gap-4 sm:grid-cols-2 lg:grid-cols-3 - Alternating section backgrounds: use
bg-backgroundandbg-muted/50
Dark Mode Setup
21st.dev components use CSS variables with dark: prefixes. Ensure:
// In layout.tsx or providers
import { ThemeProvider } from "next-themes"
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
{children}
</ThemeProvider>
Install next-themes: npm install next-themes
Font Setup
import { Geist, Geist_Mono } from "next/font/google";
const geist = Geist({ variable: "--font-sans", subsets: ["latin"] });
const geistMono = Geist_Mono({ variable: "--font-mono", subsets: ["latin"] });
<body className={`${geist.variable} ${geistMono.variable} font-sans antialiased`}>
Phase 7: Customization & Refinement
After installing components, customize them to fit the project:
- Content — Replace placeholder text, images, and links with real content
- Colors — Choose brand color intentionally (see Color Selection below)
- Typography — Ensure consistent font sizes and weights
- Spacing — Align padding/margin with the rest of the page
- Animations — Add or tune transitions using Tailwind or framer-motion
- Responsiveness — Test at mobile, tablet, and desktop breakpoints
Color Selection (CRITICAL — Avoid AI Purple Bias)
AI models have a strong bias toward purple/violet as the default brand color. This is because purple dominates tech/AI branding (Figma, Notion AI, Copilot) and shadcn/ui examples. Using purple every time is an obvious AI fingerprint — like using the Sparkles icon.
Rule: NEVER default to purple. Choose colors based on the product type and industry:
| Product / Industry | Recommended Primary | Avoid |
|---|---|---|
| Finance / Banking | Deep blue (oklch(0.45 0.15 250)), Navy, Teal |
Purple, Neon |
| Health / Wellness | Green (oklch(0.55 0.18 155)), Teal, Soft blue |
Red, Purple |
| E-commerce / Retail | Orange (oklch(0.65 0.2 50)), Coral, Amber |
Muted grays |
| Developer tools | Emerald (oklch(0.55 0.17 160)), Cyan, Slate |
Purple (overused) |
| Creative / Design | Rose (oklch(0.6 0.18 10)), Amber, Indigo |
Plain blue |
| Education | Blue (oklch(0.5 0.16 250)), Teal, Green |
Neon, Dark themes |
| Food / Restaurant | Warm red (oklch(0.55 0.22 25)), Orange, Olive |
Cold blues |
| AI / Writing tools | Teal (oklch(0.55 0.12 195)), Blue-green, Slate |
Purple (cliché!) |
| Enterprise / B2B | Slate blue (oklch(0.5 0.1 255)), Navy, Steel |
Bright neons |
| Social / Community | Coral (oklch(0.6 0.17 25)), Sky blue, Warm pink |
Dull grays |
If the user specifies a brand color, use it. If not, pick from the table above — but NEVER purple unless the user explicitly asks for it.
How to apply the chosen color:
/* globals.css — example with teal for an AI writing tool */
:root {
--brand: oklch(0.55 0.12 195); /* Teal, NOT purple */
}
Then use bg-brand, text-brand, border-brand/30 etc. throughout the site. Update hero gradients, CTA buttons, icon backgrounds, and accent colors to match.
Hero Visual Quality Checklist
Hero sections make or break the first impression. After installing a hero component, ensure:
- Heading contrast: On colored/gradient backgrounds, use solid
text-foregroundinstead of gradient-text effects (bg-clip-text text-transparent) which can be too faint - Background gradients: Apply gradients directly on the section element (
bg-gradient-to-b from-[color] via-[color] to-white) — don't layer decorative gradient divs behind opaque parents - Product mockups: For SaaS sites, build a realistic inline mockup (editor, dashboard, chat) instead of using a placehold.co image. Include window chrome (red/yellow/green dots), sidebar, content area, and status indicators. This dramatically improves perceived quality.
- CTA styling: Use
rounded-xl, visible shadows (shadow-lg), and brand colors. Add hover effects (hover:-translate-y-0.5 transition-transform) - Radial glow accents: Add subtle radial gradients using
rgba()colors (not oklch) for depth behind hero content - Avoid AI-cliché icons: NEVER use Sparkles/Stars/Wand icons — they instantly signal "AI-generated." Use minimal alternatives: a pulsing dot indicator, a small "NEW" badge, or just well-styled text. The goal is to look like a senior human designer made it, not an AI.
- Avoid AI-cliché colors: NEVER default to purple/violet. Choose colors from the Color Selection table based on the product type. Purple is the #1 AI color bias.
CSS Variable Theming
/* globals.css */
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 0 0% 3.9%;
--primary: 0 0% 9%;
--primary-foreground: 0 0% 98%;
/* ... customize these to match brand */
}
.dark {
--background: 0 0% 3.9%;
--foreground: 0 0% 98%;
/* ... dark variants */
}
}
Phase 8: Verification (THOROUGH)
This phase catches the bugs that ruin the user's first impression. Do not skip any step.
Step 1: Build passes
npm run build
Fix any TypeScript or build errors before proceeding.
Step 2: Visual inspection (MOST IMPORTANT)
Run npm run dev and actually look at every section of the page:
-
Take a screenshot or use preview_screenshot — look at the full page from top to bottom
-
Check for these common problems:
- Blank/white sections — content exists in DOM but invisible? Check CSS variables, text color matches background
- Content overflow — text or elements going off-screen to the right? Check container width, remove
text-centeror adjustmax-w - Giant blank spaces — hero taking up too much vertical space? Reduce
min-h-screentomin-h-[80vh] - Misaligned sections — some sections centered, others left-aligned? Normalize container classes
- Broken images — placeholder URLs not loading? Replace with real images or remove
-
Scroll through the entire page — every section must be visible and properly styled
Step 3: Responsiveness
Test at 3 breakpoints using preview_resize or browser devtools:
- Mobile (375px): single column, readable text, no horizontal overflow
- Tablet (768px): proper grid transition
- Desktop (1280px): full layout as designed
Step 4: Interactions
- Click every button and link
- Test navbar dropdown/mobile menu
- Test any toggles or tabs
Step 5: Console check
No errors in browser console. Warnings about missing images or unused vars are acceptable.
If any visual issue is found in Steps 2-3, fix it immediately before presenting to the user. The most common fixes are: adjusting container width, fixing CSS variable colors, and reducing hero height.
Advanced Patterns
Component Dependency Chain
Some 21st.dev components depend on other components. The npx installer handles this automatically, but be aware:
- A
Dialogcomponent may installButtonas a dependency - If you've already customized
Button, the dialog install might overwrite it - Install from leaf components up, and keep track of what's been customized
Mixing Authors Safely
When combining components from different authors:
- Check that all use the same CSS variable naming (most shadcn-based ones do)
- Normalize border-radius: pick one style and apply globally via CSS variables
- Ensure animation timing is consistent (ease-in-out, duration-200)
- Watch for conflicting Tailwind config extensions
Building Component Variations
If 21st.dev doesn't have exactly what you need:
- Find the closest match
- Install it
- Modify the source code directly (you own it!)
- The component file is in your project — edit freely
Updating Component Knowledge
At the start of every build session, refresh your knowledge of available components by browsing the relevant category pages on 21st.dev. The platform adds new components daily, so what was the best option last week might be surpassed by something better today.
This means: if you last browsed https://21st.dev/s/hero an hour ago, browse it again if you're starting a new build. Fresh data leads to better component choices.
Error Recovery
| Problem | Solution |
|---|---|
| Component not found | Try alternative spellings, browse the parent category, or search with WebSearch |
| npx install fails | Check for missing peer deps, verify URL format, try npm install for deps first |
| Component looks wrong | Check if Tailwind config was updated, verify CSS variables are defined |
| Dark mode broken | Ensure ThemeProvider wraps the app, check CSS variable definitions |
| TypeScript errors | Check component's expected props, install missing @types packages |
| Styling conflicts | Check for conflicting Tailwind classes, CSS variable naming collisions |
| 21st.dev unreachable | Use WebSearch to find component names, construct install URLs from cached knowledge |
| Component too complex | Simplify by removing unused features from the source code |
render prop errors |
Component uses @base-ui/react pattern — convert to asChild pattern |
| Giant blank space | Hero/section using min-h-screen — reduce to min-h-[80vh] or remove |
| Content off-screen right | Container width mismatch — add max-w-7xl mx-auto wrapper |
| Invisible text | CSS variables undefined — check globals.css has all required color tokens |
| Faint/invisible cards | Background gradient too subtle — use bg-card border border-border/60 shadow-sm |
| Marquee cards hidden | Edge fade w-1/3 too wide — reduce to w-1/6 |
| Gradient not showing | Using -z-10 behind parent bg-background — apply gradient directly on section |
| oklch gradient broken | oklch renders poorly in radial-gradient() — use rgba() hex values instead |
| Heading invisible on gradient | bg-clip-text text-transparent too faint — use solid text-foreground |
MCP Setup (Optional)
For AI-powered component generation, set up the Magic MCP:
npx @21st-dev/cli@latest install claude --api-key <YOUR_API_KEY>
Get API key: https://21st.dev/settings/api-keys
Manual config in .claude/settings.json:
{
"mcpServers": {
"@21st-dev/magic": {
"command": "npx",
"args": ["-y", "@21st-dev/magic@latest"],
"env": { "API_KEY": "your-api-key" }
}
}
}
MCP provides these tools:
21st_magic_component_builder— Generate components from descriptions21st_magic_component_inspiration— Browse component ideaslogo_search— Find company logos (via SVGL)