# Install grani in a new Vite app

A new Vue app from the Vite template, with Tailwind 4 and grani.

## 1. Create the app

```bash
npm create vite@latest my-app -- --template vue-ts
cd my-app
```

With another package manager: `pnpm create vite my-app --template vue-ts && cd my-app`, `yarn create vite my-app --template vue-ts && cd my-app`, `bun create vite my-app --template vue-ts && cd my-app`.

## 2. Add Tailwind

Install Tailwind 4 and its Vite plugin, then add the plugin to the config.

```bash
npm i tailwindcss @tailwindcss/vite
```

With another package manager: `pnpm add tailwindcss @tailwindcss/vite`, `yarn add tailwindcss @tailwindcss/vite`, `bun add tailwindcss @tailwindcss/vite`.

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

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

## 3. Install grani

```bash
npm i grani
```

With another package manager: `pnpm add grani`, `yarn add grani`, `bun add grani`.

## 4. Register grani

Register grani on your Vue app with `createGrani()`.

```ts
// src/main.ts
import { createApp } from 'vue'
import { createGrani } from 'grani'
import './style.css'
import App from './App.vue'

createApp(App).use(createGrani()).mount('#app')
```

## 5. Replace the styles

To customize the theme, add your token overrides below these imports. See [Theming](/guide/theming) for details, or generate brand colors on the [Theme](/theme) page.

```css
/* src/style.css */
@import 'tailwindcss';
@import 'grani/style.css';
```

## 6. Try a form

Replace `src/App.vue`. `UiToaster` displays notifications: mount it once near the root of your app, and `UiConfirm` beside it when you ask questions with `useConfirm()`. Enter a name and select Save: a toast confirms the example is working.

```vue
<!-- src/App.vue -->
<script setup lang="ts">
import { ref } from 'vue'
import { UiButton, UiField, UiInput, UiToaster, useToast } from 'grani'

const name = ref('')
const toast = useToast()
function save() {
  toast.success(`${name.value} saved`)
}
</script>

<template>
  <form class="flex flex-col gap-4 p-4" @submit.prevent="save">
    <UiField label="Client name"><UiInput v-model="name" /></UiField>
    <UiButton type="submit" :disabled="!name.trim()">Save</UiButton>
  </form>
  <UiToaster />
</template>
```

## 7. Run it

```bash
npm run dev
```

With another package manager: `pnpm dev`, `yarn dev`, `bun dev`.

## Optional: auto-import components

Automatically import grani components used in your templates with `GraniResolver`.

```bash
npm i -D unplugin-vue-components
```

With another package manager: `pnpm add -D unplugin-vue-components`, `yarn add -D unplugin-vue-components`, `bun add -d unplugin-vue-components`.

```ts
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import tailwindcss from '@tailwindcss/vite'
import Components from 'unplugin-vue-components/vite'
import { GraniResolver } from 'grani/resolver'

export default defineConfig({
  plugins: [vue(), tailwindcss(), Components({ resolvers: [GraniResolver()] })],
})
```
