Migration to v4
Nuxt UI v4 marks a major milestone: Nuxt UI and Nuxt UI Pro are now unified into a single, fully open-source and free library. You now have access to 100+ production-ready components, all available in the @nuxt/ui
package.
This guide provides step-by-step instructions to migrate your application from v3 to v4.
Migrate your project
From Nuxt UI Pro
- Replace
@nuxt/ui-pro
with@nuxt/ui
in yourpackage.json
:
pnpm remove @nuxt/ui-pro
pnpm add @nuxt/ui@alpha
yarn remove @nuxt/ui-pro
yarn add @nuxt/ui@alpha
npm uninstall @nuxt/ui-pro
npm install @nuxt/ui@alpha
bun remove @nuxt/ui-pro
bun add @nuxt/ui@alpha
- Replace
@nuxt/ui-pro
with@nuxt/ui
in yournuxt.config.ts
:
export default defineNuxtConfig({
modules: [
- '@nuxt/ui-pro',
+ '@nuxt/ui'
]
})
- Replace
@nuxt/ui-pro
with@nuxt/ui
in yourvite.config.ts
:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
- import uiPro from '@nuxt/ui-pro/vite'
+ import ui from '@nuxt/ui/vite'
export default defineConfig({
plugins: [
vue(),
- uiPro({
+ ui({
ui: {
colors: {
primary: 'green',
neutral: 'slate'
}
}
})
]
})
- Use the
ui
key instead ofuiPro
in yourapp.config.ts
:
export default defineAppConfig({
ui: {
colors: {
primary: 'green',
neutral: 'slate'
},
+ pageCard: {
+ slots: {
+ root: 'rounded-xl',
+ }
+ }
},
- uiPro: {
- pageCard: {
- slots: {
- root: 'rounded-xl',
- }
- }
- }
})
- Use the
ui
key instead ofuiPro
in yourvite.config.ts
:
export default defineConfig({
plugins: [
vue(),
ui({
ui: {
colors: {
primary: 'green',
neutral: 'slate'
},
+ pageCard: {
+ slots: {
+ root: 'rounded-xl',
+ }
+ }
},
- uiPro: {
- pageCard: {
- slots: {
- root: 'rounded-xl',
- }
- }
- }
})
]
})
- Replace
@nuxt/ui-pro
with@nuxt/ui
in your CSS:
@import "tailwindcss";
- @import "@nuxt/ui-pro";
+ @import "@nuxt/ui";
@import "tailwindcss";
- @import "@nuxt/ui-pro";
+ @import "@nuxt/ui";
From Nuxt UI
- When upgrading from Nuxt UI v3, you simply need to update to v4:
pnpm add @nuxt/ui@alpha
yarn add @nuxt/ui@alpha
npm install @nuxt/ui@alpha
bun add @nuxt/ui@alpha
Changes from v3
After upgrading to Nuxt UI v4, please note the following important changes:
Merged components
Nuxt UI Pro components have been integrated into the main @nuxt/ui
package. You can keep using them as before, but you now need to import from @nuxt/ui
instead of @nuxt/ui-pro
:
- import type { BannerProps } from '@nuxt/ui-pro'
+ import type { BannerProps } from '@nuxt/ui'
Renamed components
Several components have been renamed for better consistency:
ButtonGroup
has been replaced withFieldGroup
:
<template>
- <UButtonGroup>
+ <UFieldGroup>
<UButton label="Button" />
<UButton icon="i-lucide-chevron-down" />
- </UButtonGroup>
+ </UFieldGroup>
</template>
PageMarquee
has been replaced withMarquee
:
<template>
- <UPageMarquee :items="items" />
+ <UMarquee :items="items" />
</template>
Removed components
Some components have been removed in favor of more standard alternatives:
PageAccordion
has been replaced withAccordion
:
<template>
- <UPageAccordion :items="faqItems" />
+ <UAccordion :items="items" :unmount-on-hide="false" :ui="{ trigger: 'text-base', body: 'text-base text-muted' }" />
</template>
AI SDK v5 migration (optional)
This section only applies if you're using the AI SDK and chat components (ChatMessage
, ChatMessages
, ChatPrompt
, ChatPromptSubmit
, ChatPalette
). If you're not using AI features, you can skip this section.
- Update
@ai-sdk/vue
andai
dependencies in yourpackage.json
:
{
"dependencies": {
- "@ai-sdk/vue": "^1.2.x",
+ "@ai-sdk/vue": "^2.0.x",
- "ai": "^4.3.x"
+ "ai": "^5.0.x"
}
}
useChat
composable has been replaced with the newChat
class:
<script setup lang="ts">
- import { useChat } from '@ai-sdk/vue'
+ import { Chat } from '@ai-sdk/vue'
+ import type { UIMessage } from 'ai'
- const { messages, input, handleSubmit, status, error, reload, setMessages } = useChat()
+ const messages: UIMessage[] = []
+ const input = ref('')
+
+ const chat = new Chat({
+ messages
+ })
+
+ function handleSubmit(e: Event) {
+ e.preventDefault()
+ chat.sendMessage({ text: input.value })
+ input.value = ''
+ }
</script>
- Messages now use
parts
instead ofcontent
:
// When manually creating messages
- setMessages([{
+ messages.push({
id: '1',
role: 'user',
- content: 'Hello world'
+ parts: [{ type: 'text', text: 'Hello world' }]
- }])
+ })
// In templates
<template>
- <UChatMessage :content="message.content" />
+ <UChatMessage :parts="message.parts" />
</template>
- Some methods have been renamed:
// Regenerate the last message
- reload()
+ chat.regenerate()
// Access chat state
- :messages="messages"
- :status="status"
+ :messages="chat.messages"
+ :status="chat.status"
- New
getTextFromMessage
utility to extract text from AI SDK v5 message parts:
<script setup lang="ts">
import { getTextFromMessage } from '@nuxt/ui/utils/ai'
</script>
<template>
<UChatMessages :messages="chat.messages" :status="chat.status">
<template #content="{ message }">
<!-- Extract text from message parts and render with MDC -->
<MDC :value="getTextFromMessage(message)" :cache-key="message.id" unwrap="p" />
</template>
</UChatMessages>
</template>
modelModifiers
for UInput
and UTextarea
Updated
The modelModifiers
shape used by UInput
and UTextarea
has changed in v4:
- The
nullify
modifier was renamed tonullable
(it converts empty/blank values tonull
). - A new
optional
modifier was added (it converts empty/blank values toundefined
).
Examples:
- <UInput v-model.nullify="value" />
+ <UInput v-model.nullable="value" />
- <UTextarea v-model="value" :model-modifiers="{ nullify: true }" />
+ <UTextarea v-model="value" :model-modifiers="{ nullable: true }" />
Use nullable
when you want empty values as null
, and optional
when you prefer undefined
for absent values.