From scratch
Build a minimal Vue app with Vite, Tailwind CSS and grani. This guide walks through each file without using a starter template.
1. Install the packages
npm i vue graninpm i -D vite @vitejs/plugin-vue tailwindcss @tailwindcss/vite
2. Configure Vite
vite.config.tsimport { defineConfig } from 'vite'import vue from '@vitejs/plugin-vue'import tailwindcss from '@tailwindcss/vite' export default defineConfig({ plugins: [vue(), tailwindcss()],})
3. Write the page
Save it as
index.htmlin the root of the app.<!doctype html><html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>My app</title> </head> <body> <div id="app"></div> <script type="module" src="/src/main.ts"></script> </body></html>
4. Start the app
Register grani on your Vue app with
createGrani().src/main.tsimport { createApp } from 'vue'import { createGrani } from 'grani'import './style.css'import App from './App.vue' createApp(App).use(createGrani()).mount('#app')
6. Try a form
UiToasterdisplays notifications: mount it once near the root of your app, andUiConfirmbeside it when you ask questions withuseConfirm(). 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. Run it
npm exec viteOptional: auto-import components
Automatically import grani components used in your templates with
GraniResolver.npm i -D unplugin-vue-componentsvite.config.tsimport { 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()] })],})