Skip to content

New project

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

  1. 1. Create the app

    npm create vite@latest my-app -- --template vue-tscd my-app
  2. 2. Add Tailwind

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

    npm i tailwindcss @tailwindcss/vite
    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. 3. Install grani

    npm i grani
  4. 4. Register grani

    Register grani on your Vue app with createGrani().

    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. 5. Replace the styles

    To customize the theme, add your token overrides below these imports. See Theming for details, or generate brand colors on the Theme page.

    src/style.css
    @import 'tailwindcss';@import 'grani/style.css';
  6. 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.

    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. 7. Run it

    npm run dev
  8. Optional: auto-import components

    Automatically import grani components used in your templates with GraniResolver.

    npm i -D unplugin-vue-components
    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()] })],})