@noartem/shadcn-vue
shadcn-vue for Vue/Nuxt with Reka UI components and Tailwind. Use for accessible UI, Auto Form, data tables, charts, dark mode, MCP server setup, or encountering component imports, Reka UI errors.
| name | shadcn-vue |
| description | shadcn-vue for Vue/Nuxt with Reka UI components and Tailwind. Use for accessible UI, Auto Form, data tables, charts, dark mode, or encountering component imports, Reka UI errors. |
shadcn-vue
A framework for building ui, components and design systems. Components are added as source code to the user's project via the CLI.
IMPORTANT: Run all CLI commands using the project's package runner:
npx shadcn-vue@latest,pnpm dlx shadcn-vue@latest, orbunx --bun shadcn-vue@latest— based on the project'spackageManager. Examples below usenpx shadcn-vue@latestbut substitute the correct runner for the project.
Current Project Context
!`npx shadcn-vue@latest info --json`
The JSON above contains the project config and installed components. Use npx shadcn-vue@latest docs <component> to get documentation and example URLs for any component.
Principles
- Use existing components first. Use
npx shadcn-vue@latest searchto check registries before writing custom UI. Check community registries too. - Compose, don't reinvent. Settings page = Tabs + Card + form controls. Dashboard = Sidebar + Card + Chart + Table.
- Use built-in variants before custom styles.
variant="outline",size="sm", etc. - Use semantic colors.
bg-primary,text-muted-foreground— never raw values likebg-blue-500.
Critical Rules
These rules are always enforced. Each links to a file with Incorrect/Correct code pairs.
Styling & Tailwind → rules/styling.md
classfor layout, not styling. Never override component colors or typography.- No
space-x-*orspace-y-*. Useflexwithgap-*. For vertical stacks,flex flex-col gap-*. - Use
size-*when width and height are equal.size-10notw-10 h-10. - Use
truncateshorthand. Notoverflow-hidden text-ellipsis whitespace-nowrap. - No manual
dark:color overrides. Use semantic tokens (bg-background,text-muted-foreground). - Use
cn()for conditional classes. Don't write manual template literal ternaries. - No manual
z-indexon overlay components. Dialog, Sheet, Popover, etc. handle their own stacking.
Forms & Inputs → rules/forms.md
- Forms use
FieldGroup+Field. Never use rawdivwithspace-y-*orgrid gap-*for form layout. InputGroupusesInputGroupInput/InputGroupTextarea. Never rawInput/TextareainsideInputGroup.- Buttons inside inputs use
InputGroup+InputGroupAddon. - Option sets (2–7 choices) use
ToggleGroup. Don't loopButtonwith manual active state. FieldSet+FieldLegendfor grouping related checkboxes/radios. Don't use adivwith a heading.- Field validation uses
data-invalid+aria-invalid.data-invalidonField,aria-invalidon the control. For disabled:data-disabledonField,disabledon the control.
Component Structure → rules/composition.md
- Items always inside their Group.
SelectItem→SelectGroup.DropdownMenuItem→DropdownMenuGroup.CommandItem→CommandGroup. - Dialog, Sheet, and Drawer always need a Title.
DialogTitle,SheetTitle,DrawerTitlerequired for accessibility. Useclass="sr-only"if visually hidden. - Use full Card composition.
CardHeader/CardTitle/CardDescription/CardContent/CardFooter. Don't dump everything inCardContent. - Button has no
isPending/isLoading. Compose withSpinner+data-icon+disabled. TabsTriggermust be insideTabsList. Never render triggers directly inTabs.Avataralways needsAvatarFallback. For when the image fails to load.
Use Components, Not Custom Markup → rules/composition.md
- Use existing components before custom markup. Check if a component exists before writing a styled
div. - Callouts use
Alert. Don't build custom styled divs. - Empty states use
Empty. Don't build custom empty state markup. - Toast via
vue-sonner. Usetoast()fromvue-sonner. - Use
Separatorinstead of<hr>or<div class="border-t">. - Use
Skeletonfor loading placeholders. No customanimate-pulsedivs. - Use
Badgeinstead of custom styled spans.
Icons → rules/icons.md
- Icons in
Buttonusedata-icon.data-icon="inline-start"ordata-icon="inline-end"on the icon. - No sizing classes on icons inside components. Components handle icon sizing via CSS. No
size-4orw-4 h-4. - Pass icons as objects, not string keys.
:icon="CheckIcon", not a string lookup. - Use project's
iconLibraryfor imports. CheckiconLibraryfrom project context. Never assume@lucide/vue.
CLI
- Apply preset codes directly with the CLI. Use
npx shadcn-vue@latest apply <code>for existing projects, ornpx shadcn-vue@latest init --preset <code>when initializing.
Key Patterns
These are the most common patterns that differentiate correct shadcn-vue code. For edge cases, see the linked rule files above.
<!-- Form layout: FieldGroup + Field, not div + Label. -->
<FieldGroup>
<Field>
<FieldLabel for="email">Email</FieldLabel>
<Input id="email" />
</Field>
</FieldGroup>
<!-- Validation: data-invalid on Field, aria-invalid on the control. -->
<Field data-invalid>
<FieldLabel>Email</FieldLabel>
<Input aria-invalid />
<FieldDescription>Invalid email.</FieldDescription>
</Field>
<!-- Icons in buttons: data-icon, no sizing classes. -->
<Button>
<SearchIcon data-icon="inline-start" />
Search
</Button>
<!-- Spacing: gap-*, not space-y-*. -->
<div class="flex flex-col gap-4"> <!-- correct -->
<div class="space-y-4"> <!-- wrong -->
<!-- Equal dimensions: size-*, not w-* h-*. -->
<Avatar class="size-10"> <!-- correct -->
<Avatar class="w-10 h-10"> <!-- wrong -->
<!-- Status colors: Badge variants or semantic tokens, not raw colors. -->
<Badge variant="secondary">+20.1%</Badge> <!-- correct -->
<span class="text-emerald-600">+20.1%</span> <!-- wrong -->
Component Selection
| Need | Use |
|---|---|
| Button/action | Button with appropriate variant |
| Form inputs | Input, Select, Combobox, Switch, Checkbox, RadioGroup, Textarea, InputOTP, Slider |
| Toggle between 2–7 options | ToggleGroup + ToggleGroupItem |
| Data display | Table, Card, Badge, Avatar |
| Navigation | Sidebar, NavigationMenu, Breadcrumb, Tabs, Pagination |
| Overlays | Dialog (modal), Sheet (side panel), Drawer (bottom sheet), AlertDialog (confirmation) |
| Feedback | vue-sonner (toast), Alert, Progress, Skeleton, Spinner |
| Command palette | Command inside Dialog |
| Charts | Chart (wraps Unovis) |
| Layout | Card, Separator, Resizable, ScrollArea, Accordion, Collapsible |
| Empty states | Empty |
| Menus | DropdownMenu, ContextMenu, Menubar |
| Tooltips/info | Tooltip, HoverCard, Popover |
Key Fields
The injected project context contains these key fields:
aliases→ use the actual alias prefix for imports (e.g.@/,~/), never hardcode.tailwindVersion→"v4"uses@theme inlineblocks;"v3"usestailwind.config.js.tailwindCssFile→ the global CSS file where custom CSS variables are defined. Always edit this file, never create a new one.style→ component visual treatment (e.g.nova,vega).base→ primitive library (reka). Affects component APIs and available props.iconLibrary→ determines icon imports. Use@lucide/vueforlucide,@tabler/icons-vuefortabler, etc. Never assume@lucide/vue.resolvedPaths→ exact file-system destinations for components, utils, hooks, etc.framework→ routing and file conventions (e.g. Nuxt vs Vite SPA).packageManager→ use this for any non-shadcn-vue dependency installs (e.g.pnpm add date-fnsvsnpm install date-fns).
See cli.md — info command for the full field reference.
Component Docs, Examples, and Usage
Run npx shadcn-vue@latest docs <component> to get the URLs for a component's documentation, examples, and API reference. Fetch these URLs to get the actual content.
npx shadcn-vue@latest docs button dialog select
When creating, fixing, debugging, or using a component, always run npx shadcn-vue@latest docs and fetch the URLs first. This ensures you're working with the correct API and usage patterns rather than guessing.
For per-component documentation, see components/<component>.md in this skill (70 components auto-generated from the official repo).
Workflow
- Get project context — already injected above. Run
npx shadcn-vue@latest infoagain if you need to refresh. - Check installed components first — before running
add, always check thecomponentslist from project context or list theresolvedPaths.uidirectory. Don't import components that haven't been added, and don't re-add ones already installed. - Find components —
npx shadcn-vue@latest search. - Get docs and examples — run
npx shadcn-vue@latest docs <component>to get URLs, then fetch them. Usenpx shadcn-vue@latest viewto browse registry items you haven't installed. To preview changes to installed components, usenpx shadcn-vue@latest add --diff. - Install or update —
npx shadcn-vue@latest add. When updating existing components, use--dry-runand--diffto preview changes first (see Updating Components below). - Fix imports in third-party components — After adding components from community registries, check the added non-UI files for hardcoded import paths like
@/components/ui/.... These won't match the project's actual aliases. Usenpx shadcn-vue@latest infoto get the correctuialias (e.g.@workspace/ui/components) and rewrite the imports accordingly. The CLI rewrites imports for its own UI files, but third-party registry components may use default paths that don't match the project. - Review added components — After adding a component or block from any registry, always read the added files and verify they are correct. Check for missing sub-components (e.g.
SelectItemwithoutSelectGroup), missing imports, incorrect composition, or violations of the Critical Rules. Also replace any icon imports with the project'siconLibraryfrom the project context (e.g. if the registry item uses@lucide/vuebut the project useshugeicons, swap the imports and icon names accordingly). Fix all issues before moving on. - Registry must be explicit — When the user asks to add a block or component, do not guess the registry. If no registry is specified (e.g. user says "add a login block" without specifying
@shadcn, etc.), ask which registry to use. Never default to a registry on behalf of the user. - Switching presets — Ask the user first: overwrite, merge, or skip?
- Overwrite:
npx shadcn-vue@latest apply <code>. Overwrites detected components, fonts, and CSS variables. - Merge:
npx shadcn-vue@latest init --preset <code> --force --no-reinstall, then runnpx shadcn-vue@latest infoto list installed components, then for each installed component use--dry-runand--diffto smart merge it individually. - Skip:
npx shadcn-vue@latest init --preset <code> --force --no-reinstall. Only updates config and CSS, leaves components as-is. - Important: Always run preset commands inside the user's project directory.
applyonly works in an existing project with acomponents.jsonfile. The CLI automatically preserves the current base (reka) fromcomponents.json. If you must use a scratch/temp directory (e.g. for--dry-runcomparisons), pass--base <current-base>explicitly — preset codes do not encode the base.
- Overwrite:
Updating Components
When the user asks to update a component from upstream while keeping their local changes, use --dry-run and --diff to intelligently merge. NEVER fetch raw files from GitHub manually — always use the CLI.
- Run
npx shadcn-vue@latest add <component> --dry-runto see all files that would be affected. - For each file, run
npx shadcn-vue@latest add <component> --diff <file>to see what changed upstream vs local. - Decide per file based on the diff:
- No local changes → safe to overwrite.
- Has local changes → read the local file, analyze the diff, and apply upstream updates while preserving local modifications.
- User says "just update everything" → use
--overwrite, but confirm first.
- Never use
--overwritewithout the user's explicit approval.
Quick Reference
# Create a new project.
npx shadcn-vue@latest init --name my-app --preset nova
npx shadcn-vue@latest init --name my-app --preset a2r6bw --template vite
# Initialize existing project.
npx shadcn-vue@latest init --preset nova
npx shadcn-vue@latest init --defaults # shortcut: --template=nuxt --preset=nova (base style implied)
# Apply a preset to an existing project.
npx shadcn-vue@latest apply a2r6bw
# Add components.
npx shadcn-vue@latest add button card dialog
npx shadcn-vue@latest add --all
# Search registries.
npx shadcn-vue@latest search @shadcn -q "sidebar"
# Get component docs and example URLs.
npx shadcn-vue@latest docs button dialog select
# View registry item details (for items not yet installed).
npx shadcn-vue@latest view @shadcn/button
# Get project info.
npx shadcn-vue@latest info
npx shadcn-vue@latest info --json
Named presets: nova, vega, maia, lyra, mira, luma
Templates: nuxt, vite, astro, laravel
Preset codes: Version-prefixed base62 strings (e.g. a2r6bw), from shadcn-vue.com.
Quick Start (3 Minutes)
For Vue Projects (Vite)
1. Initialize shadcn-vue
npx shadcn-vue@latest init
During initialization:
- Style:
New YorkorDefault(cannot change later!) - Base color:
Slate(recommended) - CSS variables:
Yes(required for dark mode)
2. Configure TypeScript Path Aliases
// tsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}
3. Configure Vite
// vite.config.ts
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import tailwindcss from "@tailwindcss/vite"; // Tailwind v4
import path from "path";
export default defineConfig({
plugins: [vue(), tailwindcss()],
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
},
});
4. Add Your First Component
npx shadcn-vue@latest add button
Bundled Resources
Templates (templates/):
quick-setup.ts- Complete setup guide for Vue/Nuxt with examples (190 lines)
References (references/):
cli.md- CLI commands, flags, presets, templates, smart mergetheming.md- Theming andcssVariableserror-catalog.md- All 7 documented issues with solutions (267 lines)component-examples.md- All 50+ component examples with codedark-mode-setup.md- Complete dark mode implementation guidedata-tables.md- Data tables with TanStack Table
Rules (references/rules/):
styling.md- Semantic colors, variants, class, spacing, size, truncate, dark mode, cn(), z-indexforms.md- FieldGroup, Field, InputGroup, ToggleGroup, FieldSet, validation statescomposition.md- Groups, overlays, Card, Tabs, Avatar, Alert, Empty, Toast, Separator, Skeleton, Badge, Button loadingicons.md- data-icon, icon sizing, passing icons as objects, iconLibrary
Component Documentation (components/):
references/components.md- Index of all shadcn-vue components (70)components/<component>.md- Individual component documentation with installation, usage, and examples
Official Documentation:
- shadcn-vue Docs: https://shadcn-vue.com
- Reka UI Docs: https://reka-ui.com
- GitHub: https://github.com/unovue/shadcn-vue
When to Load References
Load these references based on the task:
Load
references/rules/styling.mdwhen:- Writing or reviewing component markup with Tailwind classes
- User encounters styling issues or inconsistent appearance
- Need to verify correct use of semantic tokens, spacing, sizing
- Trigger phrases: "style", "color", "spacing", "gap", "dark mode", "class"
Load
references/rules/forms.mdwhen:- Building forms or working with form controls
- User needs accessible form field patterns
- Working with InputGroup, ToggleGroup, FieldSet, or validation states
- Trigger phrases: "form", "input", "field", "validation", "toggle group"
Load
references/rules/composition.mdwhen:- Composing multiple components together
- Building dialogs, cards, menus, tabs, or overlay components
- User asks which component to use for a given UI pattern
- Trigger phrases: "dialog", "card", "tabs", "menu", "overlay", "empty state", "alert"
Load
references/rules/icons.mdwhen:- Adding icons to buttons or other components
- Troubleshooting icon sizing or alignment issues
- Need to determine correct icon import package
- Trigger phrases: "icon", "lucide", "tabler", "data-icon"
Load
references/error-catalog.mdwhen:- User encounters "component not found" or import errors
- Setup commands fail or configuration issues arise
- Tailwind CSS variables or TypeScript paths broken
- Trigger phrases: "not working", "error", "fails to", "broken"
Load
references/components.mdwhen:- User asks what components are available (names, categories, status)
- User needs to add/use a component and wants the correct install/import paths
- You need to confirm a component exists before recommending a custom build
Load
references/component-examples.mdwhen:- User asks "how do I implement [component]?"
- Need copy-paste examples for specific components
- Building forms, tables, navigation, or data display
- Trigger phrases: "example", "how to use", "implement", "code sample"
Load
references/cli.mdwhen:- User asks how to run the CLI (
init,add,update,search,view,docs,info,apply) or what prompts mean - Need the exact command/flags for installing one or more components
- Working with presets, templates, or switching presets
- Troubleshooting CLI-related issues (registry, paths, overwrites)
- User asks how to run the CLI (
Load
references/dark-mode-setup.mdwhen:- Implementing dark mode / theme switching
- User mentions Vue 3 + Vite, Nuxt, or Astro setup
- Need composable patterns for theme management
- Trigger phrases: "dark mode", "theme", "light/dark", "color scheme"
Load
references/theming.mdwhen:- User wants to customize theme tokens via CSS variables (
cssVariables,:root,.dark) - Need to wire Tailwind to CSS-variable-based colors and radii
- Setting up/adjusting design tokens (colors, radius, typography) for shadcn-vue
- User wants to customize theme tokens via CSS variables (
Load
references/data-tables.mdwhen:- Building sortable/filterable/paginated tables
- User mentions TanStack Table or
DataTable - Trigger phrases: "data table", "table", "tanstack", "sorting", "pagination"
Critical Setup Rules
Always Do
✅ Run init before adding components
- Creates required configuration and utilities
- Sets up path aliases
✅ Use CSS variables for theming (cssVariables: true)
- Enables dark mode support
- Flexible theme customization
✅ Configure TypeScript path aliases
- Required for component imports
- Must match
components.jsonaliases
✅ Keep components.json in version control
- Team members need same configuration
- Documents project setup
Never Do
❌ Don't change style after initialization
- Requires complete reinstall
- Reinitialize in new directory instead
❌ Don't mix Radix Vue and Reka UI v2
- Incompatible component APIs
- Use one or the other
❌ Don't skip TypeScript configuration
- Component imports will fail
- IDE autocomplete won't work
❌ Don't use without Tailwind CSS
- Components are styled with Tailwind
- Won't render correctly
Common Mistakes
- Running
addbeforeinitand missingcomponents.json. - Using CSS variable classes without
tailwind.cssVariables: true. - Hardcoding
@/imports instead of readingaliasesfrom project context. - Fetching component files from GitHub manually instead of using the CLI.
- Using
--overwritewithout user confirmation. - Guessing registry names instead of asking the user.
Configuration
shadcn-vue uses components.json to configure:
- Component paths (
@/components/ui) - Utils location (
@/lib/utils) - Tailwind config paths
- TypeScript paths
- Icon library
- Custom registries
Full example: See templates/components.json or generate via npx shadcn-vue@latest init
Utils Library
The @/lib/utils.ts file provides the cn() helper for merging Tailwind classes:
- Combines multiple className strings
- Uses
clsx+tailwind-mergefor conflict resolution
Auto-generated by shadcn-vue init - no manual setup needed.
Loading...
Select a file to preview
Analyzing security...
Checking scan reports and verification data.
Bill of Materials
Everything this skill can do — files, network, commands, and more.