Vite

Set up the two things create-vite leaves out — Tailwind and the @ alias.

A fresh Vite project has neither of the two things nat-ui needs: Tailwind, and an import alias. Next.js projects arrive with both, which is why this page is only about Vite. Neither is something the CLI will set up for you, so do both before running init.

Install Tailwind

nat-ui styles its components with Tailwind, and init writes theme variables into a stylesheet that imports it. Without one it stops rather than guessing, so this comes first.

pnpm add tailwindcss @tailwindcss/vite

Add the plugin to your Vite config:

vite.config.ts
import tailwindcss from '@tailwindcss/vite'
import react from '@vitejs/plugin-react'
import {defineConfig} from 'vite'

export default defineConfig({
  plugins: [react(), tailwindcss()],
})

Then replace the contents of src/index.css, which create-vite fills with starter styles, with the import:

src/index.css
@import 'tailwindcss';

Add the alias

create-vite configures no import alias, so a fresh project has no idea what @/ means. Skip this and add writes perfectly good files that do not compile, with the first error coming from a file you did not write:

src/App.tsx(1,22): error TS2307: Cannot find module '@/components/ui/button'
src/components/ui/button.tsx(4,18): error TS2307: Cannot find module '@/lib/utils'

init warns when it sees this, but it will not edit your TypeScript config for you — which config compiles your application is a guess from the outside, and guessing wrong writes to a file that changes nothing.

The config that compiles your application is tsconfig.app.json. Add paths inside its compilerOptions:

tsconfig.app.json
{
  "compilerOptions": {
    "paths": {"@/*": ["./src/*"]}
  }
}

Then add the same block to tsconfig.json. That copy compiles nothing — the root file is a solution file, with "files": [] and references to the configs that do the real work — so it exists purely so tools looking in the conventional place can discover your alias. init is one of them:

tsconfig.json
{
  "files": [],
  "references": [{"path": "./tsconfig.app.json"}, {"path": "./tsconfig.node.json"}],
  "compilerOptions": {
    "paths": {"@/*": ["./src/*"]}
  }
}

That is the whole change. Vite resolves TypeScript's paths itself, so no resolve.alias entry in vite.config.ts is needed.

Guides written against older toolchains pair paths with baseUrl, and build a resolve.alias from __dirname. Neither belongs in a current project. TypeScript 6 rejects baseUrl outright with TS5101: Option 'baseUrl' is deprecated, and Vite 8 warns that __dirname is unsupported by its config loader. A relative paths target resolves against the file it is written in, so baseUrl has nothing left to do.

Then run init

pnpm dlx @nat-ui/cli@latest init

With the alias in place, init detects @ from your tsconfig.json rather than falling back to a guess, and everything after this point works the same as it does anywhere else.

pnpm dlx @nat-ui/cli@latest add button

On this page