4 steps · ~5 min · Vue 3 / Nuxt

Setup. One command.

Tokens, helpers, and the theme composable — installed with one npx. Files copy into your repo. You own them.

Bootstrap

npx shadcn-vue@latest addhttps://uipkge.dev/r/nuxt/init.json-y
01

Install Tailwind v4

Nuxt 4 · ~20s

shadcn-vue's preflight refuses to write components when it can't find a Tailwind setup (No Tailwind CSS configuration found), so wire Tailwind v4 in first. If you're not on Nuxt, follow tailwindcss.com/docs/installation then jump to step 02.

  1. 1. Install Tailwind v4 + the Vite plugin

    $ npm install -D tailwindcss @tailwindcss/vite typescript
  2. 2. Create a placeholder CSS entry

    shadcn-vue probes for a Tailwind-importing CSS file before it does anything. Step 03 overwrites this file with the full OKLCH token set, so the placeholder is throwaway. Create app/assets/css/tailwind.css in your editor and paste in:

    app/assets/css/tailwind.css
    @import url('https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,100..1000;1,9..40,100..1000&family=Anybody:wght@600;700;800&display=swap');
    @import 'tailwindcss';
    @import 'tw-animate-css';
    
    @custom-variant dark (&:is(.dark *));
    
  3. 3. Wire the Vite plugin + CSS in nuxt.config.ts

    nuxt.config.ts
    import tailwindcss from '@tailwindcss/vite'
    
    export default defineNuxtConfig({
      css: ['~/assets/css/tailwind.css'],
      components: [{ path: '~/components', pathPrefix: false }],
      vite: { plugins: [tailwindcss()] }
    })
02

Pre-write components.json

Recommended · ~5s

You can let npx shadcn-vue add scaffold this for you, but the CLI fires interactive prompts (icon library / font / base color) before it reads -y, and it won't pre-register the @uipkge named registry. Writing it yourself skips both. Our registry items target ~/app/... directly (Nuxt 4 srcDir), so files land in the right place regardless of how the CLI resolves the @/ aliases below.

Create components.json at the project root and paste this in:

components.json
{
  "$schema": "https://shadcn-vue.com/schema.json",
  "style": "new-york",
  "typescript": true,
  "tailwind": {
    "config": "",
    "css": "app/assets/css/tailwind.css",
    "baseColor": "neutral",
    "cssVariables": true,
    "prefix": ""
  },
  "iconLibrary": "lucide",
  "aliases": {
    "components": "@/components",
    "composables": "@/composables",
    "utils": "@/lib/utils",
    "ui": "@/components/ui",
    "lib": "@/lib"
  },
  "registries": {
    "@uipkge": "https://uipkge.dev/r/nuxt/{name}.json"
  }
}
03

Bootstrap your project

~10s · 4 files
Run this
$ npx shadcn-vue@latest add https://uipkge.dev/r/nuxt/init.json -y

With components.json already in place from step 02, the CLI resolves init.json's three transitive deps (tailwind tokens, cn(), useTheme) and writes four files. You'll see a single prompt mid-install: "The file ../../assets/css/tailwind.css already exists. Would you like to overwrite? (y/N)" — press Enter (default N). The token merge has already run; the prompt is only asking whether to overwrite your file with a smaller bootstrap copy, which would lose the merged tokens. The "Circular dependency detected" notice you may see before the prompt is a benign upstream resolver quirk.

Drops these into your repo — yours to edit, no upgrades.

04

Add any component

114 primitives · 50 blocks
Add the button (any name works)
$ npx shadcn-vue@latest add https://uipkge.dev/r/nuxt/button.json -y

Paste the URL of any item from /components or /blocks. Transitive registry deps come along.

05

Sanity check

app.vue (or any .vue file)
import { Button } from '@/components/ui/button'

// then in your template:
//   <Button>Hello uipkge</Button>
See a styled button? You're set.
06

Known rough edges

Cosmetic noise you'll see during install. None of these break anything; they're listed so you can ignore them without wondering.

  • "Circular dependency detected in registry items" during init.json. False positive from shadcn-vue's resolver — the init{tailwind, utils, use-theme} graph is acyclic. Install completes cleanly.
  • "Two component files resolving to the same name UiButton" after adding any primitive. Nuxt sees both Button.vue and index.ts as resolving to UiButton. Harmless — your explicit import { Button } from '@/components/ui/button' wins. Will quiet once shadcn-vue's generated index files learn to opt out of auto-import.
  • First dev start after install is slow while Vite optimises the new dependency graph (reka-ui, lucide-vue-next, class-variance-authority, etc). Subsequent starts are instant.
  • Why we use tailwind.css and not the Nuxt-default main.css. The tailwind registry item ships two independent install actions: a file-write (target hard-coded in the manifest: ~/app/assets/css/tailwind.css) and a token-merge (target read from components.json's tailwind.css field). If those two paths differ, you get two CSS files — one with the real tokens, one with a 10-line bootstrap entry that's never loaded. Naming both tailwind.css (the docs default above) makes them converge on a single file. Use main.css if you prefer the Nuxt convention — just delete the orphan after install. The shadcn-vue CLI rejects files: [] on registry items, otherwise we'd ship cssVars-only.