UIPackage
Menu
6 sections · ~5 min · Vue (Nuxt 4)

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 add https://uipkge.dev/r/vue/init.json -y
Named registry: npx shadcn-vue@latest add @uipkge/init -y
01

Install Tailwind v4

Nuxt 4 · ~20s

The shadcn-vue 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 4, follow tailwindcss.com/docs/installation then jump to step 02.

  1. 1. Install Tailwind v4 + the Vite plugin

    terminal
    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 "tailwindcss";

    Skip the echo '...' > file shell trick — it writes a UTF-16 BOM under PowerShell that Vite rejects, and CMD has no mkdir -p. Create the file in your editor.

  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()] }
    })

    components: [{ pathPrefix: false }] keeps blocks in sub-folders of components/ from registering as <BlocksDashboardLayout> instead of <DashboardLayout>.

02

Pre-write components.json

Recommended · ~5s

You can let npx shadcn-vue add scaffold this, 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, 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/vue/{name}.json"
  }
}
03

Bootstrap your project

~10s · 4 files
$ npx shadcn-vue@latest add https://uipkge.dev/r/vue/init.json -y
Named registry: npx shadcn-vue@latest add @uipkge/init -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 4 files. You may see a single overwrite prompt for the CSS file mid-install — press Enter (default N); the token merge has already run. The "Circular dependency detected" notice you may see is a benign upstream resolver quirk.

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

04

Add any component

118 primitives · 50 blocks

Copy the source into your project — you own it, no semver, edit freely. Install by direct URL, or register the named registry once and use the @uipkge/<name> short form anywhere.

$ npx shadcn-vue@latest add https://uipkge.dev/r/vue/button.json
Named registry: npx shadcn-vue@latest add @uipkge/button

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

Or register the named registry once in components.json:

components.json
{
  "registries": {
    "@uipkge": "https://uipkge.dev/r/vue/{name}.json"
  }
}

Configure once, then @uipkge/<name> works anywhere shadcn-vue does.

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 the 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. Harmless — your explicit import { Button } from '@/components/ui/button' wins.
  • First dev start after install is slow while Vite optimises the new dependency graph (reka-ui / radix, lucide, 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 a file-write (target hard-coded to ~/app/assets/css/tailwind.css) and a token-merge (target read from components.json ). If those paths differ you get two CSS files — naming both tailwind.css makes them converge on one.