| name | better-design-shadcn-themes |
| description | Install and use themed shadcn/ui components from 31+ design systems (Linear, Stripe, Apple, Notion, etc.) with one command |
| triggers | ["install shadcn component with custom theme","add Linear styled button to my project","use better-design components","apply Stripe design system to shadcn","install themed shadcn components","browse available design systems for shadcn","add Apple themed UI components","customize shadcn with design system themes"] |
better-design-shadcn-themes
Skill by ara.so — Design Skills collection.
Overview
Better Design provides 31+ production-ready design systems for shadcn/ui. Each design system includes ~89 fully themed components (buttons, cards, dialogs, forms, etc.) that you can install directly into your shadcn/ui project with a single CLI command. All design systems are MIT licensed and include popular styles like Linear, Stripe, Airbnb, Apple, Notion, Vercel, Supabase, and Figma.
Browse all design systems at: https://better-design.com/design-systems
Installation
Better Design components install directly into existing shadcn/ui projects using the shadcn CLI. There's no separate package to install — you pull individual components on-demand.
Prerequisites
Your project must already have shadcn/ui initialized:
npx shadcn@latest init
Core Commands
Install a Single Component
npx shadcn@latest add https://www.better-design.com/registry/<design-system>/<component>.json
Examples:
npx shadcn@latest add https://www.better-design.com/registry/linear/button.json
npx shadcn@latest add https://www.better-design.com/registry/stripe/card.json
npx shadcn@latest add https://www.better-design.com/registry/apple/dialog.json
npx shadcn@latest add https://www.better-design.com/registry/notion/input.json
The CLI automatically:
- Downloads the component TypeScript file
- Installs required dependencies
- Updates CSS variables in
globals.css
- Handles component dependencies
Install Multiple Components
npx shadcn@latest add \
https://www.better-design.com/registry/linear/button.json \
https://www.better-design.com/registry/linear/input.json \
https://www.better-design.com/registry/linear/card.json
Available Design Systems
| Design System Slug | Style | Best For |
|---|
linear | Clean, modern, dark | Project management, SaaS |
stripe | Professional, minimal | Fintech, payments |
apple | Polished, refined | Consumer apps |
notion | Soft, approachable | Note-taking, docs |
vercel | Sleek, high-contrast | Developer tools |
supabase | Bold, green accent | Backend tools, dashboards |
figma | Colorful, playful | Design tools |
airbnb | Warm, friendly | Marketplace, social |
beam-lib | Gradient, modern | Creative tools |
corporate-fintech | Conservative, trust | Enterprise, finance |
glassmorphic-dark | Frosted glass effect | Modern dark UIs |
minimal-light | Ultra-clean light | Content-first apps |
midnight-glass | Dark with glass | Premium apps |
vibrant-dark | High-saturation dark | Gaming, entertainment |
Full list of 31 design systems: https://better-design.com/design-systems
Component Usage Patterns
Basic Component Import
After installing a component, import and use it like any shadcn component:
import { Button } from "@/components/ui/button"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Input } from "@/components/ui/input"
export default function MyPage() {
return (
<Card>
<CardHeader>
<CardTitle>Linear-styled Card</CardTitle>
</CardHeader>
<CardContent>
<Input placeholder="Enter text..." />
<Button>Submit</Button>
</CardContent>
</Card>
)
}
Mixing Design Systems
You can install components from different design systems in the same project:
import { Button } from "@/components/ui/button"
import { Card } from "@/components/ui/card"
export default function MixedDesign() {
return (
<Card className="p-6">
<h2>Checkout</h2>
<Button>Pay with Linear button style</Button>
</Card>
)
}
Note: CSS variables may conflict when mixing design systems. For best results, stick to one design system per project or carefully test combinations.
Form Components Example
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Textarea } from "@/components/ui/textarea"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
export default function ContactForm() {
return (
<form className="space-y-4">
<div>
<Label htmlFor="name">Name</Label>
<Input id="name" placeholder="John Doe" />
</div>
<div>
<Label htmlFor="email">Email</Label>
<Input id="email" type="email" placeholder="john@example.com" />
</div>
<div>
<Label htmlFor="topic">Topic</Label>
<Select>
<SelectTrigger id="topic">
<SelectValue placeholder="Select a topic" />
</SelectTrigger>
<SelectContent>
<SelectItem value="support">Support</SelectItem>
<SelectItem value="sales">Sales</SelectItem>
<SelectItem value="feedback">Feedback</SelectItem>
</SelectContent>
</Select>
</div>
<div>
<Label htmlFor="message">Message</Label>
<Textarea id="message" placeholder="Your message..." />
</div>
<Button type="submit">Send Message</Button>
</form>
)
}
Dialog Component Example
import { Button } from "@/components/ui/button"
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
export default function EditProfileDialog() {
return (
<Dialog>
<DialogTrigger asChild>
<Button variant="outline">Edit Profile</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Edit profile</DialogTitle>
<DialogDescription>
Make changes to your profile here. Click save when you're done.
</DialogDescription>
</DialogHeader>
<div className="grid gap-4 py-4">
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="username" className="text-right">
Username
</Label>
<Input id="username" defaultValue="@johndoe" className="col-span-3" />
</div>
</div>
<DialogFooter>
<Button type="submit">Save changes</Button>
</DialogFooter>
</DialogContent>
</Dialog>
)
}
Data Table Example
import {
Table,
TableBody,
TableCaption,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
const invoices = [
{ id: "INV001", status: "Paid", amount: "$250.00" },
{ id: "INV002", status: "Pending", amount: "$150.00" },
{ id: "INV003", status: "Paid", amount: "$350.00" },
]
export default function InvoiceTable() {
return (
<Table>
<TableCaption>A list of your recent invoices.</TableCaption>
<TableHeader>
<TableRow>
<TableHead>Invoice</TableHead>
<TableHead>Status</TableHead>
<TableHead>Amount</TableHead>
<TableHead className="text-right">Actions</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{invoices.map((invoice) => (
<TableRow key={invoice.id}>
<TableCell className="font-medium">{invoice.id}</TableCell>
<TableCell>
<Badge variant={invoice.status === "Paid" ? "default" : "secondary"}>
{invoice.status}
</Badge>
</TableCell>
<TableCell>{invoice.amount}</TableCell>
<TableCell className="text-right">
<Button variant="ghost" size="sm">View</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
)
}
Available Components
Each design system includes ~89 components:
Layout & Structure:
accordion, card, separator, tabs, table
Forms & Input:
button, input, textarea, checkbox, radio-group, select, slider, switch, form, label
Feedback & Overlays:
dialog, alert-dialog, drawer, sheet, popover, tooltip, toast, alert, badge, progress, skeleton
Navigation:
navigation-menu, menubar, dropdown-menu, context-menu, breadcrumb, pagination, command
Data Display:
avatar, calendar, chart, carousel, collapsible, data-table, hover-card, aspect-ratio
Typography:
Configuration
CSS Variables
Each design system uses CSS variables defined in globals.css. When you install your first component from a design system, the CLI updates globals.css with theme tokens:
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 0 0% 3.9%;
--card: 0 0% 100%;
--card-foreground: 0 0% 3.9%;
--primary: 0 0% 9%;
--primary-foreground: 0 0% 98%;
}
.dark {
--background: 0 0% 3.9%;
--foreground: 0 0% 98%;
}
}
These variables are automatically configured — you don't need to manually edit them.
Tailwind Configuration
Better Design components use your existing shadcn Tailwind config. Ensure your tailwind.config.ts has the shadcn setup:
import type { Config } from "tailwindcss"
const config: Config = {
darkMode: ["class"],
content: [
"./pages/**/*.{ts,tsx}",
"./components/**/*.{ts,tsx}",
"./app/**/*.{ts,tsx}",
"./src/**/*.{ts,tsx}",
],
theme: {
extend: {
colors: {
border: "hsl(var(--border))",
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
primary: {
DEFAULT: "hsl(var(--primary))",
foreground: "hsl(var(--primary-foreground))",
},
},
borderRadius: {
lg: "var(--radius)",
md: "calc(var(--radius) - 2px)",
sm: "calc(var(--radius) - 4px)",
},
},
},
plugins: [require("tailwindcss-animate")],
}
export default config
Repository Structure
If forking or contributing to the Better Design repo:
registry/
<design-system>/
button.json # Registry entry for shadcn CLI
card.json
input.json
...
index.json # Registry manifest
components/
<design-system>/
components/ui/ # Readable TypeScript source
button.tsx
card.tsx
...
globals.css # CSS variables for the theme
lib/utils.ts # cn() utility
registry/ — Source of truth for CLI installations (JSON format)
components/ — Human-readable .tsx files for browsing/copying
Both directories stay in sync. When forking, copy both the component and matching globals.css.
Common Patterns
Creating a Landing Page Hero
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
export default function Hero() {
return (
<section className="flex min-h-screen flex-col items-center justify-center px-4">
<h1 className="text-5xl font-bold tracking-tight">
Ship faster with Better Design
</h1>
<p className="mt-4 text-xl text-muted-foreground">
31+ design systems for shadcn/ui. Install with one command.
</p>
<div className="mt-8 flex gap-4">
<Button size="lg">Get Started</Button>
<Button size="lg" variant="outline">View Designs</Button>
</div>
<div className="mt-12 flex w-full max-w-md gap-2">
<Input placeholder="Enter your email..." type="email" />
<Button>Subscribe</Button>
</div>
</section>
)
}
Building a Dashboard Layout
import { Button } from "@/components/ui/button"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { Progress } from "@/components/ui/progress"
export default function Dashboard() {
return (
<div className="p-8">
<div className="flex items-center justify-between">
<h1 className="text-3xl font-bold">Dashboard</h1>
<Button>Create New</Button>
</div>
<Tabs defaultValue="overview" className="mt-6">
<TabsList>
<TabsTrigger value="overview">Overview</TabsTrigger>
<TabsTrigger value="analytics">Analytics</TabsTrigger>
<TabsTrigger value="reports">Reports</TabsTrigger>
</TabsList>
<TabsContent value="overview" className="mt-6">
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
<Card>
<CardHeader>
<CardTitle>Total Revenue</CardTitle>
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">$45,231.89</div>
<p className="text-xs text-muted-foreground">
+20.1% from last month
</p>
<Progress value={60} className="mt-2" />
</CardContent>
</Card>
{/* More cards... */}
</div>
</TabsContent>
</Tabs>
</div>
)
}
Authentication Form
import { Button } from "@/components/ui/button"
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Separator } from "@/components/ui/separator"
export default function LoginForm() {
return (
<Card className="w-full max-w-md">
<CardHeader>
<CardTitle>Sign In</CardTitle>
<CardDescription>
Enter your email and password to access your account
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="space-y-2">
<Label htmlFor="email">Email</Label>
<Input id="email" type="email" placeholder="name@example.com" />
</div>
<div className="space-y-2">
<Label htmlFor="password">Password</Label>
<Input id="password" type="password" />
</div>
<Button className="w-full">Sign In</Button>
<div className="relative">
<Separator />
<span className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 bg-background px-2 text-xs text-muted-foreground">
OR CONTINUE WITH
</span>
</div>
<Button variant="outline" className="w-full">
GitHub
</Button>
</CardContent>
<CardFooter className="flex justify-center">
<p className="text-sm text-muted-foreground">
Don't have an account? <a href="#" className="underline">Sign up</a>
</p>
</CardFooter>
</Card>
)
}
Troubleshooting
Components Don't Match Preview
Problem: Installed component looks different from the Better Design website preview.
Solutions:
- Ensure
globals.css was updated by the CLI (check for CSS variables)
- Verify your Tailwind config includes shadcn color definitions
- Check that you're importing from the correct path:
@/components/ui/[component]
- Clear Next.js cache:
rm -rf .next and restart dev server
CSS Variables Not Applied
Problem: Components render but colors/spacing are wrong.
Solution: Check that globals.css is imported in your root layout:
import "@/app/globals.css"
Type Errors After Installation
Problem: TypeScript errors on component imports.
Solutions:
- Restart TypeScript server in your editor
- Check
tsconfig.json has correct path alias:
{
"compilerOptions": {
"paths": {
"@/*": ["./*"]
}
}
}
- Run
npm install to ensure all dependencies are installed
Mixing Design Systems
Problem: Components from different design systems clash visually.
Best Practice: Stick to one design system per project for consistency. If you must mix:
- Use different design systems for distinct sections (e.g., marketing site vs. app dashboard)
- Test thoroughly in both light and dark modes
- Be prepared to manually adjust CSS variables
Component Dependencies Missing
Problem: Error about missing component dependency (e.g., Button needs Label).
Solution: Install the missing component from the same design system:
npx shadcn@latest add https://www.better-design.com/registry/linear/label.json
The shadcn CLI usually handles dependencies automatically, but occasionally you may need to manually install related components.
Contributing
To contribute a new design system or component:
- Fork the repository: https://github.com/marvkr/better-design
- Create both
registry/<design-system>/ and components/<design-system>/ directories
- Add component JSON files to
registry/ following shadcn registry format
- Add matching
.tsx files to components/<design-system>/components/ui/
- Include
globals.css with theme CSS variables
- Update
registry/index.json manifest
- Submit a pull request
All design systems must be MIT licensed and include at least 20+ core components.