@plutocms/supabase 0.0.1-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/nuxt/GENERATION.md +5 -0
- package/.agents/skills/nuxt/SKILL.md +55 -0
- package/.agents/skills/nuxt/references/advanced-hooks.md +289 -0
- package/.agents/skills/nuxt/references/advanced-layers.md +299 -0
- package/.agents/skills/nuxt/references/advanced-module-authoring.md +554 -0
- package/.agents/skills/nuxt/references/best-practices-data-fetching.md +357 -0
- package/.agents/skills/nuxt/references/best-practices-ssr.md +355 -0
- package/.agents/skills/nuxt/references/core-cli.md +263 -0
- package/.agents/skills/nuxt/references/core-config.md +162 -0
- package/.agents/skills/nuxt/references/core-data-fetching.md +236 -0
- package/.agents/skills/nuxt/references/core-deployment.md +224 -0
- package/.agents/skills/nuxt/references/core-directory-structure.md +269 -0
- package/.agents/skills/nuxt/references/core-modules.md +292 -0
- package/.agents/skills/nuxt/references/core-routing.md +226 -0
- package/.agents/skills/nuxt/references/features-components-autoimport.md +328 -0
- package/.agents/skills/nuxt/references/features-components.md +264 -0
- package/.agents/skills/nuxt/references/features-composables.md +276 -0
- package/.agents/skills/nuxt/references/features-server.md +265 -0
- package/.agents/skills/nuxt/references/features-state.md +194 -0
- package/.agents/skills/nuxt/references/rendering-modes.md +237 -0
- package/.agents/skills/nuxt-ui/SKILL.md +334 -0
- package/.agents/skills/nuxt-ui/references/components.md +377 -0
- package/.agents/skills/nuxt-ui/references/composables.md +127 -0
- package/.agents/skills/nuxt-ui/references/layouts/chat.md +195 -0
- package/.agents/skills/nuxt-ui/references/layouts/dashboard.md +220 -0
- package/.agents/skills/nuxt-ui/references/layouts/docs.md +141 -0
- package/.agents/skills/nuxt-ui/references/layouts/editor.md +167 -0
- package/.agents/skills/nuxt-ui/references/layouts/page.md +260 -0
- package/.agents/skills/nuxt-ui/references/theming.md +427 -0
- package/.agents/skills/supabase-postgres-best-practices/AGENTS.md +68 -0
- package/.agents/skills/supabase-postgres-best-practices/CLAUDE.md +1 -0
- package/.agents/skills/supabase-postgres-best-practices/README.md +116 -0
- package/.agents/skills/supabase-postgres-best-practices/SKILL.md +64 -0
- package/.agents/skills/supabase-postgres-best-practices/references/advanced-full-text-search.md +55 -0
- package/.agents/skills/supabase-postgres-best-practices/references/advanced-jsonb-indexing.md +49 -0
- package/.agents/skills/supabase-postgres-best-practices/references/conn-idle-timeout.md +46 -0
- package/.agents/skills/supabase-postgres-best-practices/references/conn-limits.md +44 -0
- package/.agents/skills/supabase-postgres-best-practices/references/conn-pooling.md +41 -0
- package/.agents/skills/supabase-postgres-best-practices/references/conn-prepared-statements.md +46 -0
- package/.agents/skills/supabase-postgres-best-practices/references/data-batch-inserts.md +54 -0
- package/.agents/skills/supabase-postgres-best-practices/references/data-n-plus-one.md +53 -0
- package/.agents/skills/supabase-postgres-best-practices/references/data-pagination.md +50 -0
- package/.agents/skills/supabase-postgres-best-practices/references/data-upsert.md +50 -0
- package/.agents/skills/supabase-postgres-best-practices/references/lock-advisory.md +56 -0
- package/.agents/skills/supabase-postgres-best-practices/references/lock-deadlock-prevention.md +68 -0
- package/.agents/skills/supabase-postgres-best-practices/references/lock-short-transactions.md +50 -0
- package/.agents/skills/supabase-postgres-best-practices/references/lock-skip-locked.md +54 -0
- package/.agents/skills/supabase-postgres-best-practices/references/monitor-explain-analyze.md +45 -0
- package/.agents/skills/supabase-postgres-best-practices/references/monitor-pg-stat-statements.md +55 -0
- package/.agents/skills/supabase-postgres-best-practices/references/monitor-vacuum-analyze.md +55 -0
- package/.agents/skills/supabase-postgres-best-practices/references/query-composite-indexes.md +44 -0
- package/.agents/skills/supabase-postgres-best-practices/references/query-covering-indexes.md +40 -0
- package/.agents/skills/supabase-postgres-best-practices/references/query-index-types.md +48 -0
- package/.agents/skills/supabase-postgres-best-practices/references/query-missing-indexes.md +43 -0
- package/.agents/skills/supabase-postgres-best-practices/references/query-partial-indexes.md +45 -0
- package/.agents/skills/supabase-postgres-best-practices/references/schema-constraints.md +80 -0
- package/.agents/skills/supabase-postgres-best-practices/references/schema-data-types.md +46 -0
- package/.agents/skills/supabase-postgres-best-practices/references/schema-foreign-key-indexes.md +59 -0
- package/.agents/skills/supabase-postgres-best-practices/references/schema-lowercase-identifiers.md +55 -0
- package/.agents/skills/supabase-postgres-best-practices/references/schema-partitioning.md +55 -0
- package/.agents/skills/supabase-postgres-best-practices/references/schema-primary-keys.md +61 -0
- package/.agents/skills/supabase-postgres-best-practices/references/security-privileges.md +54 -0
- package/.agents/skills/supabase-postgres-best-practices/references/security-rls-basics.md +50 -0
- package/.agents/skills/supabase-postgres-best-practices/references/security-rls-performance.md +57 -0
- package/.editorconfig +12 -0
- package/.env.example +2 -0
- package/.eslintignore +1 -0
- package/.prettierrc +9 -0
- package/.vscode/extensions.json +10 -0
- package/.vscode/settings.json +61 -0
- package/README.md +62 -0
- package/app/components/navbar/NavbarAdmin.vue +169 -0
- package/app/composables/auth.ts +81 -0
- package/app/layouts/setup.vue +13 -0
- package/app/middleware/auth.ts +27 -0
- package/app/middleware/setup-check.ts +25 -0
- package/app/pages/admin/(auth)/login.vue +84 -0
- package/app/pages/admin/(auth)/signup.vue +128 -0
- package/app/pages/admin/settings.vue +116 -0
- package/app/pages/admin/setup.vue +300 -0
- package/app/pages/admin.vue +38 -0
- package/bun.lock +2685 -0
- package/eslint.config.mjs +88 -0
- package/nuxt.config.ts +55 -0
- package/package.json +44 -0
- package/public/schema.sql +103 -0
- package/scripts/supabase-typegen.ts +36 -0
- package/server/api/category/list.get.ts +9 -0
- package/server/api/category/new.post.ts +31 -0
- package/server/api/settings/first_setup.get.ts +39 -0
- package/server/api/settings/index.get.ts +27 -0
- package/server/api/settings/update.post.ts +36 -0
- package/server/api/setup/create.post.ts +58 -0
- package/server/api/signup.post.ts +28 -0
- package/server/api/users/[id].get.ts +21 -0
- package/server/api/users/index.get.ts +16 -0
- package/shared/types/supabase.ts +406 -0
- package/skills-lock.json +20 -0
- package/tsconfig.json +18 -0
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rendering-modes
|
|
3
|
+
description: Universal rendering, client-side rendering, and hybrid rendering in Nuxt
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Rendering Modes
|
|
7
|
+
|
|
8
|
+
Nuxt supports multiple rendering modes: universal (SSR), client-side (CSR), and hybrid rendering.
|
|
9
|
+
|
|
10
|
+
## Universal Rendering (Default)
|
|
11
|
+
|
|
12
|
+
Server renders HTML, then hydrates on client:
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
// nuxt.config.ts - this is the default
|
|
16
|
+
export default defineNuxtConfig({
|
|
17
|
+
ssr: true,
|
|
18
|
+
})
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**Benefits:**
|
|
22
|
+
- Fast initial page load (HTML is ready)
|
|
23
|
+
- SEO-friendly (content is in HTML)
|
|
24
|
+
- Works without JavaScript initially
|
|
25
|
+
|
|
26
|
+
**How it works:**
|
|
27
|
+
1. Server executes Vue code, generates HTML
|
|
28
|
+
2. Browser displays HTML immediately
|
|
29
|
+
3. JavaScript loads and hydrates the page
|
|
30
|
+
4. Page becomes fully interactive
|
|
31
|
+
|
|
32
|
+
## Client-Side Rendering
|
|
33
|
+
|
|
34
|
+
Render entirely in the browser:
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
// nuxt.config.ts
|
|
38
|
+
export default defineNuxtConfig({
|
|
39
|
+
ssr: false,
|
|
40
|
+
})
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Benefits:**
|
|
44
|
+
- Simpler development (no SSR constraints)
|
|
45
|
+
- Cheaper hosting (static files only)
|
|
46
|
+
- Works offline
|
|
47
|
+
|
|
48
|
+
**Use cases:**
|
|
49
|
+
- Admin dashboards
|
|
50
|
+
- SaaS applications
|
|
51
|
+
- Apps behind authentication
|
|
52
|
+
|
|
53
|
+
### SPA Loading Template
|
|
54
|
+
|
|
55
|
+
Provide loading UI while app hydrates:
|
|
56
|
+
|
|
57
|
+
```html
|
|
58
|
+
<!-- app/spa-loading-template.html -->
|
|
59
|
+
<div class="loading">
|
|
60
|
+
<div class="spinner"></div>
|
|
61
|
+
<p>Loading...</p>
|
|
62
|
+
</div>
|
|
63
|
+
|
|
64
|
+
<style>
|
|
65
|
+
.loading {
|
|
66
|
+
display: flex;
|
|
67
|
+
flex-direction: column;
|
|
68
|
+
align-items: center;
|
|
69
|
+
justify-content: center;
|
|
70
|
+
height: 100vh;
|
|
71
|
+
}
|
|
72
|
+
.spinner {
|
|
73
|
+
width: 40px;
|
|
74
|
+
height: 40px;
|
|
75
|
+
border: 4px solid #f3f3f3;
|
|
76
|
+
border-top: 4px solid #00dc82;
|
|
77
|
+
border-radius: 50%;
|
|
78
|
+
animation: spin 1s linear infinite;
|
|
79
|
+
}
|
|
80
|
+
@keyframes spin {
|
|
81
|
+
to { transform: rotate(360deg); }
|
|
82
|
+
}
|
|
83
|
+
</style>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Hybrid Rendering
|
|
87
|
+
|
|
88
|
+
Mix rendering modes per route using route rules:
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
// nuxt.config.ts
|
|
92
|
+
export default defineNuxtConfig({
|
|
93
|
+
routeRules: {
|
|
94
|
+
// Static pages - prerendered at build
|
|
95
|
+
'/': { prerender: true },
|
|
96
|
+
'/about': { prerender: true },
|
|
97
|
+
|
|
98
|
+
// ISR - regenerate in background
|
|
99
|
+
'/blog/**': { isr: 3600 }, // Cache for 1 hour
|
|
100
|
+
'/products/**': { swr: true }, // Stale-while-revalidate
|
|
101
|
+
|
|
102
|
+
// Client-only rendering
|
|
103
|
+
'/admin/**': { ssr: false },
|
|
104
|
+
'/dashboard/**': { ssr: false },
|
|
105
|
+
|
|
106
|
+
// Server-rendered (default)
|
|
107
|
+
'/api/**': { cors: true },
|
|
108
|
+
},
|
|
109
|
+
})
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Route Rules Reference
|
|
113
|
+
|
|
114
|
+
| Rule | Description |
|
|
115
|
+
|------|-------------|
|
|
116
|
+
| `prerender: true` | Pre-render at build time |
|
|
117
|
+
| `ssr: false` | Client-side only |
|
|
118
|
+
| `swr: number \| true` | Stale-while-revalidate caching |
|
|
119
|
+
| `isr: number \| true` | Incremental static regeneration |
|
|
120
|
+
| `cache: { maxAge: number }` | Cache with TTL |
|
|
121
|
+
| `redirect: string` | Redirect to another path |
|
|
122
|
+
| `cors: true` | Add CORS headers |
|
|
123
|
+
| `headers: object` | Custom response headers |
|
|
124
|
+
|
|
125
|
+
### Inline Route Rules
|
|
126
|
+
|
|
127
|
+
Define per-page:
|
|
128
|
+
|
|
129
|
+
```vue
|
|
130
|
+
<script setup lang="ts">
|
|
131
|
+
defineRouteRules({
|
|
132
|
+
prerender: true,
|
|
133
|
+
})
|
|
134
|
+
</script>
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Prerendering
|
|
138
|
+
|
|
139
|
+
Generate static HTML at build time:
|
|
140
|
+
|
|
141
|
+
```ts
|
|
142
|
+
// nuxt.config.ts
|
|
143
|
+
export default defineNuxtConfig({
|
|
144
|
+
// Prerender specific routes
|
|
145
|
+
routeRules: {
|
|
146
|
+
'/': { prerender: true },
|
|
147
|
+
'/about': { prerender: true },
|
|
148
|
+
'/posts/*': { prerender: true },
|
|
149
|
+
},
|
|
150
|
+
})
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Or use `nuxt generate`:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
nuxt generate
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Programmatic Prerendering
|
|
160
|
+
|
|
161
|
+
```ts
|
|
162
|
+
// nuxt.config.ts
|
|
163
|
+
export default defineNuxtConfig({
|
|
164
|
+
hooks: {
|
|
165
|
+
'prerender:routes'({ routes }) {
|
|
166
|
+
// Add dynamic routes
|
|
167
|
+
const posts = await fetchPostSlugs()
|
|
168
|
+
for (const slug of posts) {
|
|
169
|
+
routes.add(`/posts/${slug}`)
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
})
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Or in pages:
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
// server/api/posts.ts or a plugin
|
|
180
|
+
prerenderRoutes(['/posts/1', '/posts/2', '/posts/3'])
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Edge-Side Rendering
|
|
184
|
+
|
|
185
|
+
Render at CDN edge servers:
|
|
186
|
+
|
|
187
|
+
```ts
|
|
188
|
+
// nuxt.config.ts
|
|
189
|
+
export default defineNuxtConfig({
|
|
190
|
+
nitro: {
|
|
191
|
+
preset: 'cloudflare-pages', // or 'vercel-edge', 'netlify-edge'
|
|
192
|
+
},
|
|
193
|
+
})
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Supported platforms:
|
|
197
|
+
- Cloudflare Pages/Workers
|
|
198
|
+
- Vercel Edge Functions
|
|
199
|
+
- Netlify Edge Functions
|
|
200
|
+
|
|
201
|
+
## Conditional Rendering
|
|
202
|
+
|
|
203
|
+
Use `import.meta.server` and `import.meta.client`:
|
|
204
|
+
|
|
205
|
+
```vue
|
|
206
|
+
<script setup>
|
|
207
|
+
if (import.meta.server) {
|
|
208
|
+
// Server-only code
|
|
209
|
+
console.log('Running on server')
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (import.meta.client) {
|
|
213
|
+
// Client-only code
|
|
214
|
+
console.log('Running in browser')
|
|
215
|
+
}
|
|
216
|
+
</script>
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
For components:
|
|
220
|
+
|
|
221
|
+
```vue
|
|
222
|
+
<template>
|
|
223
|
+
<ClientOnly>
|
|
224
|
+
<BrowserOnlyComponent />
|
|
225
|
+
<template #fallback>
|
|
226
|
+
<p>Loading...</p>
|
|
227
|
+
</template>
|
|
228
|
+
</ClientOnly>
|
|
229
|
+
</template>
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
<!--
|
|
233
|
+
Source references:
|
|
234
|
+
- https://nuxt.com/docs/guide/concepts/rendering
|
|
235
|
+
- https://nuxt.com/docs/getting-started/prerendering
|
|
236
|
+
- https://nuxt.com/docs/api/nuxt-config#routerules
|
|
237
|
+
-->
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: nuxt-ui
|
|
3
|
+
description: Build UIs with @nuxt/ui v4 — 125+ accessible Vue components with Tailwind CSS theming. Use when creating interfaces, customizing themes to match a brand, building forms, or composing layouts like dashboards, docs sites, and chat interfaces.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Nuxt UI
|
|
7
|
+
|
|
8
|
+
Vue component library built on [Reka UI](https://reka-ui.com/) + [Tailwind CSS](https://tailwindcss.com/) + [Tailwind Variants](https://www.tailwind-variants.org/). Works with Nuxt, Vue (Vite), Laravel (Inertia), and AdonisJS (Inertia).
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
### Nuxt
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pnpm add @nuxt/ui tailwindcss
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
// nuxt.config.ts
|
|
20
|
+
export default defineNuxtConfig({
|
|
21
|
+
modules: ['@nuxt/ui'],
|
|
22
|
+
css: ['~/assets/css/main.css']
|
|
23
|
+
})
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
```css
|
|
27
|
+
/* app/assets/css/main.css */
|
|
28
|
+
@import "tailwindcss";
|
|
29
|
+
@import "@nuxt/ui";
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
```vue
|
|
33
|
+
<!-- app.vue -->
|
|
34
|
+
<template>
|
|
35
|
+
<UApp>
|
|
36
|
+
<NuxtPage />
|
|
37
|
+
</UApp>
|
|
38
|
+
</template>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Vue (Vite)
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
pnpm add @nuxt/ui tailwindcss
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
// vite.config.ts
|
|
49
|
+
import { defineConfig } from 'vite'
|
|
50
|
+
import vue from '@vitejs/plugin-vue'
|
|
51
|
+
import ui from '@nuxt/ui/vite'
|
|
52
|
+
|
|
53
|
+
export default defineConfig({
|
|
54
|
+
plugins: [
|
|
55
|
+
vue(),
|
|
56
|
+
ui()
|
|
57
|
+
]
|
|
58
|
+
})
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
// src/main.ts
|
|
63
|
+
import './assets/main.css'
|
|
64
|
+
import { createApp } from 'vue'
|
|
65
|
+
import { createRouter, createWebHistory } from 'vue-router'
|
|
66
|
+
import ui from '@nuxt/ui/vue-plugin'
|
|
67
|
+
import App from './App.vue'
|
|
68
|
+
|
|
69
|
+
const app = createApp(App)
|
|
70
|
+
|
|
71
|
+
const router = createRouter({
|
|
72
|
+
routes: [],
|
|
73
|
+
history: createWebHistory()
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
app.use(router)
|
|
77
|
+
app.use(ui)
|
|
78
|
+
app.mount('#app')
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
```css
|
|
82
|
+
/* assets/main.css */
|
|
83
|
+
@import "tailwindcss";
|
|
84
|
+
@import "@nuxt/ui";
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
```vue
|
|
88
|
+
<!-- src/App.vue -->
|
|
89
|
+
<template>
|
|
90
|
+
<UApp>
|
|
91
|
+
<RouterView />
|
|
92
|
+
</UApp>
|
|
93
|
+
</template>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
> **Vue**: Add `class="isolate"` to your root `<div id="app">` in `index.html`.
|
|
97
|
+
|
|
98
|
+
> **Vue + Inertia**: Use `ui({ router: 'inertia' })` in `vite.config.ts`.
|
|
99
|
+
|
|
100
|
+
### UApp
|
|
101
|
+
|
|
102
|
+
Wrapping your app in `UApp` is **required** — it provides global config for toasts, tooltips, and programmatic overlays. It also accepts a `locale` prop for i18n (see [composables reference](references/composables.md)).
|
|
103
|
+
|
|
104
|
+
## Icons
|
|
105
|
+
|
|
106
|
+
Nuxt UI uses [Iconify](https://iconify.design/) for 200,000+ icons. In Nuxt, `@nuxt/icon` is auto-registered. In Vue, icons work out of the box via the Vite plugin.
|
|
107
|
+
|
|
108
|
+
### Naming convention
|
|
109
|
+
|
|
110
|
+
Icons use the format `i-{collection}-{name}`:
|
|
111
|
+
|
|
112
|
+
```vue
|
|
113
|
+
<UIcon name="i-lucide-sun" class="size-5" />
|
|
114
|
+
<UButton icon="i-lucide-plus" label="Add" />
|
|
115
|
+
<UAlert icon="i-lucide-info" title="Heads up" />
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
> Browse all icons at [icones.js.org](https://icones.js.org). The `lucide` collection is used throughout Nuxt UI defaults.
|
|
119
|
+
|
|
120
|
+
### Install icon collections locally
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
pnpm i @iconify-json/lucide
|
|
124
|
+
pnpm i @iconify-json/simple-icons
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Custom local collections (Nuxt)
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
// nuxt.config.ts
|
|
131
|
+
export default defineNuxtConfig({
|
|
132
|
+
icon: {
|
|
133
|
+
customCollections: [{
|
|
134
|
+
prefix: 'custom',
|
|
135
|
+
dir: './app/assets/icons'
|
|
136
|
+
}]
|
|
137
|
+
}
|
|
138
|
+
})
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
```vue
|
|
142
|
+
<UIcon name="i-custom-my-icon" />
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Theming & Branding
|
|
146
|
+
|
|
147
|
+
Nuxt UI ships with a default look. The goal is to adapt it to your brand so every app looks unique.
|
|
148
|
+
|
|
149
|
+
**Always use semantic utilities** (`text-default`, `bg-elevated`, `border-muted`), never raw Tailwind palette colors. See [references/theming.md](references/theming.md) for the full list.
|
|
150
|
+
|
|
151
|
+
### Colors
|
|
152
|
+
|
|
153
|
+
7 semantic colors (`primary`, `secondary`, `success`, `info`, `warning`, `error`, `neutral`) configurable at runtime:
|
|
154
|
+
|
|
155
|
+
```ts
|
|
156
|
+
// Nuxt — app.config.ts
|
|
157
|
+
export default defineAppConfig({
|
|
158
|
+
ui: { colors: { primary: 'indigo', neutral: 'zinc' } }
|
|
159
|
+
})
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
// Vue — vite.config.ts
|
|
164
|
+
import { defineConfig } from 'vite'
|
|
165
|
+
import vue from '@vitejs/plugin-vue'
|
|
166
|
+
import ui from '@nuxt/ui/vite'
|
|
167
|
+
|
|
168
|
+
export default defineConfig({
|
|
169
|
+
plugins: [
|
|
170
|
+
vue(),
|
|
171
|
+
ui({
|
|
172
|
+
ui: { colors: { primary: 'indigo', neutral: 'zinc' } }
|
|
173
|
+
})
|
|
174
|
+
]
|
|
175
|
+
})
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Customizing components
|
|
179
|
+
|
|
180
|
+
**Override priority** (highest wins): `ui` prop / `class` prop > global config > theme defaults.
|
|
181
|
+
|
|
182
|
+
The `ui` prop overrides a component's **slots** after variants are computed — it wins over everything:
|
|
183
|
+
|
|
184
|
+
```vue
|
|
185
|
+
<UButton :ui="{ base: 'rounded-none', trailingIcon: 'size-3 rotate-90' }" />
|
|
186
|
+
<UCard :ui="{ header: 'bg-muted', body: 'p-8' }" />
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**Read the generated theme file** to find slot names for any component:
|
|
190
|
+
|
|
191
|
+
- **Nuxt**: `.nuxt/ui/<component>.ts`
|
|
192
|
+
- **Vue**: `node_modules/.nuxt-ui/ui/<component>.ts`
|
|
193
|
+
|
|
194
|
+
> For CSS variables, custom colors, global config, compound variants, and a **full brand customization playbook**, see [references/theming.md](references/theming.md)
|
|
195
|
+
|
|
196
|
+
## Composables
|
|
197
|
+
|
|
198
|
+
```ts
|
|
199
|
+
// Notifications
|
|
200
|
+
const toast = useToast()
|
|
201
|
+
toast.add({ title: 'Saved', color: 'success', icon: 'i-lucide-check' })
|
|
202
|
+
|
|
203
|
+
// Programmatic overlays
|
|
204
|
+
const overlay = useOverlay()
|
|
205
|
+
const modal = overlay.create(MyModal)
|
|
206
|
+
const { result } = modal.open({ title: 'Confirm' })
|
|
207
|
+
await result
|
|
208
|
+
|
|
209
|
+
// Keyboard shortcuts
|
|
210
|
+
defineShortcuts({
|
|
211
|
+
meta_k: () => openSearch(),
|
|
212
|
+
escape: () => close()
|
|
213
|
+
})
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
> For full composable reference, see [references/composables.md](references/composables.md)
|
|
217
|
+
|
|
218
|
+
## Form validation
|
|
219
|
+
|
|
220
|
+
Uses Standard Schema — works with Zod, Valibot, Yup, or Joi.
|
|
221
|
+
|
|
222
|
+
```vue
|
|
223
|
+
<script setup lang="ts">
|
|
224
|
+
import { z } from 'zod'
|
|
225
|
+
|
|
226
|
+
const schema = z.object({
|
|
227
|
+
email: z.string().email('Invalid email'),
|
|
228
|
+
password: z.string().min(8, 'Min 8 characters')
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
type Schema = z.output<typeof schema>
|
|
232
|
+
const state = reactive<Partial<Schema>>({ email: '', password: '' })
|
|
233
|
+
|
|
234
|
+
function onSubmit() {
|
|
235
|
+
// UForm validates before emitting @submit — state is valid here
|
|
236
|
+
}
|
|
237
|
+
</script>
|
|
238
|
+
|
|
239
|
+
<template>
|
|
240
|
+
<UForm :schema="schema" :state="state" @submit="onSubmit">
|
|
241
|
+
<UFormField name="email" label="Email" required>
|
|
242
|
+
<UInput v-model="state.email" type="email" />
|
|
243
|
+
</UFormField>
|
|
244
|
+
|
|
245
|
+
<UFormField name="password" label="Password" required>
|
|
246
|
+
<UInput v-model="state.password" type="password" />
|
|
247
|
+
</UFormField>
|
|
248
|
+
|
|
249
|
+
<UButton type="submit">Sign in</UButton>
|
|
250
|
+
</UForm>
|
|
251
|
+
</template>
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
> For all form components and validation patterns, see [references/components.md](references/components.md#form)
|
|
255
|
+
|
|
256
|
+
## Overlays
|
|
257
|
+
|
|
258
|
+
```vue
|
|
259
|
+
<!-- Modal -->
|
|
260
|
+
<UModal v-model:open="isOpen" title="Edit" description="Edit your profile">
|
|
261
|
+
<template #body>Content</template>
|
|
262
|
+
<template #footer>
|
|
263
|
+
<UButton variant="ghost" @click="isOpen = false">Cancel</UButton>
|
|
264
|
+
<UButton @click="save">Save</UButton>
|
|
265
|
+
</template>
|
|
266
|
+
</UModal>
|
|
267
|
+
|
|
268
|
+
<!-- Slideover (side panel) -->
|
|
269
|
+
<USlideover v-model:open="isOpen" title="Settings" side="right">
|
|
270
|
+
<template #body>Content</template>
|
|
271
|
+
</USlideover>
|
|
272
|
+
|
|
273
|
+
<!-- Dropdown menu (flat array) -->
|
|
274
|
+
<UDropdownMenu :items="[
|
|
275
|
+
{ label: 'Edit', icon: 'i-lucide-pencil' },
|
|
276
|
+
{ type: 'separator' },
|
|
277
|
+
{ label: 'Delete', icon: 'i-lucide-trash', color: 'error' }
|
|
278
|
+
]">
|
|
279
|
+
<UButton icon="i-lucide-ellipsis-vertical" variant="ghost" />
|
|
280
|
+
</UDropdownMenu>
|
|
281
|
+
|
|
282
|
+
<!-- Dropdown menu (nested array — groups with automatic separators) -->
|
|
283
|
+
<UDropdownMenu :items="[
|
|
284
|
+
[{ label: 'Edit', icon: 'i-lucide-pencil' }, { label: 'Duplicate', icon: 'i-lucide-copy' }],
|
|
285
|
+
[{ label: 'Delete', icon: 'i-lucide-trash', color: 'error' }]
|
|
286
|
+
]">
|
|
287
|
+
<UButton icon="i-lucide-ellipsis-vertical" variant="ghost" />
|
|
288
|
+
</UDropdownMenu>
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
> For all overlay components, see [references/components.md](references/components.md#overlay)
|
|
292
|
+
|
|
293
|
+
## Layouts
|
|
294
|
+
|
|
295
|
+
Nuxt UI provides components to compose full page layouts. Load the reference matching your use case:
|
|
296
|
+
|
|
297
|
+
| Layout | Description | Reference |
|
|
298
|
+
|---|---|---|
|
|
299
|
+
| Page | Landing, blog, changelog, pricing — public-facing pages | [layouts/page.md](references/layouts/page.md) |
|
|
300
|
+
| Dashboard | Admin UI with resizable sidebar and panels | [layouts/dashboard.md](references/layouts/dashboard.md) |
|
|
301
|
+
| Docs | Documentation with sidebar nav and TOC | [layouts/docs.md](references/layouts/docs.md) |
|
|
302
|
+
| Chat | AI chat with messages and prompt | [layouts/chat.md](references/layouts/chat.md) |
|
|
303
|
+
| Editor | Rich text editor with toolbars | [layouts/editor.md](references/layouts/editor.md) |
|
|
304
|
+
|
|
305
|
+
## Templates
|
|
306
|
+
|
|
307
|
+
Official starter templates at [github.com/nuxt-ui-templates](https://github.com/nuxt-ui-templates):
|
|
308
|
+
|
|
309
|
+
| Template | Framework | GitHub |
|
|
310
|
+
|---|---|---|
|
|
311
|
+
| Starter | Nuxt | [nuxt-ui-templates/starter](https://github.com/nuxt-ui-templates/starter) |
|
|
312
|
+
| Starter | Vue | [nuxt-ui-templates/starter-vue](https://github.com/nuxt-ui-templates/starter-vue) |
|
|
313
|
+
| Dashboard | Nuxt | [nuxt-ui-templates/dashboard](https://github.com/nuxt-ui-templates/dashboard) |
|
|
314
|
+
| Dashboard | Vue | [nuxt-ui-templates/dashboard-vue](https://github.com/nuxt-ui-templates/dashboard-vue) |
|
|
315
|
+
| SaaS | Nuxt | [nuxt-ui-templates/saas](https://github.com/nuxt-ui-templates/saas) |
|
|
316
|
+
| Landing | Nuxt | [nuxt-ui-templates/landing](https://github.com/nuxt-ui-templates/landing) |
|
|
317
|
+
| Docs | Nuxt | [nuxt-ui-templates/docs](https://github.com/nuxt-ui-templates/docs) |
|
|
318
|
+
| Portfolio | Nuxt | [nuxt-ui-templates/portfolio](https://github.com/nuxt-ui-templates/portfolio) |
|
|
319
|
+
| Chat | Nuxt | [nuxt-ui-templates/chat](https://github.com/nuxt-ui-templates/chat) |
|
|
320
|
+
| Editor | Nuxt | [nuxt-ui-templates/editor](https://github.com/nuxt-ui-templates/editor) |
|
|
321
|
+
| Changelog | Nuxt | [nuxt-ui-templates/changelog](https://github.com/nuxt-ui-templates/changelog) |
|
|
322
|
+
| Starter | Laravel | [nuxt-ui-templates/starter-laravel](https://github.com/nuxt-ui-templates/starter-laravel) |
|
|
323
|
+
| Starter | AdonisJS | [nuxt-ui-templates/starter-adonis](https://github.com/nuxt-ui-templates/starter-adonis) |
|
|
324
|
+
|
|
325
|
+
> When starting a new project, clone the matching template instead of setting up from scratch.
|
|
326
|
+
|
|
327
|
+
## Additional references
|
|
328
|
+
|
|
329
|
+
Load based on your task — **do not load all at once**:
|
|
330
|
+
|
|
331
|
+
- [references/theming.md](references/theming.md) — CSS variables, custom colors, component theme overrides
|
|
332
|
+
- [references/components.md](references/components.md) — all 125+ components by category with props and usage
|
|
333
|
+
- [references/composables.md](references/composables.md) — useToast, useOverlay, defineShortcuts
|
|
334
|
+
- Generated theme files — all slots, variants, and default classes for any component (Nuxt: `.nuxt/ui/<component>.ts`, Vue: `node_modules/.nuxt-ui/ui/<component>.ts`)
|