Until last week, Nuxt UI came in two halves. @nuxt/ui was the free set of form controls, overlays and navigation. @nuxt/ui-pro was a paid licence for the pieces that make a product: page heroes, pricing tables, dashboard shells, documentation layouts, blog and changelog components. The Nuxt UI v4 announcement of 22 September ends that split: version 4 is a single open-source package, licensed MIT. The announcement credits NuxtLabs joining Vercel in July for making that possible.
What shipped
From the announcement and the GitHub release:
- One package.
@nuxt/uinow contains everything, over 110 components by the announcement's count, including every component that used to need a Pro licence. - The templates that were Pro-only are free and updated for v4. The release notes name eight: Starter, Landing, Docs, SaaS, Dashboard, Chat, Portfolio and Changelog. The announcement counts twelve in total.
- The Figma kit is free, with more than 2,000 component variants and design tokens.
- The documentation is restructured under
ui.nuxt.com/docs, with separate Theme and Typography sections, anllms.txtfile and an MCP server so AI coding tools can read the component docs. - The chat components support AI SDK v5 and its parts-based messages.
- A short migration. The announcement says the release focuses on unification rather than breaking changes, but the migration guide still lists a few: two renamed components, one removed, a renamed
v-modelmodifier and two changes toUForm.
The foundation has not moved: 4.0.0 depends on Tailwind CSS 4.1 and Reka UI 2.5 (the unstyled, accessible components Nuxt UI builds on), the same versions as the last v3 release.
Set up Nuxt UI 4 in a new Nuxt project
For a new Nuxt 4 project, install the package, register the module, and import Tailwind and Nuxt UI in your CSS:
npm install @nuxt/ui
export default defineNuxtConfig({
modules: ['@nuxt/ui'],
css: ['~/assets/css/main.css'],
})
@import "tailwindcss";
@import "@nuxt/ui";
Then wrap the app once in UApp, the provider that toasts, tooltips and overlays opened from code need:
<template>
<UApp>
<NuxtPage />
</UApp>
</template>
Or skip all of that with the starter: npm create nuxt@latest -- -t ui.
With pnpm, the installation page asks you to either set shamefully-hoist=true in .npmrc or install tailwindcss at the project root yourself, so that Tailwind's imports resolve.
Nuxt UI also works in a plain Vue and Vite project through its Vite plugin, import ui from '@nuxt/ui/vite', with the same components and the same theme object passed to the plugin instead of to app.config.ts.
Use a former Pro component in any project
UPageHero was a Pro component. It now works in any Nuxt UI project, with no licence:
<script setup lang="ts">
import type { ButtonProps } from '@nuxt/ui'
const links: ButtonProps[] = [
{ label: 'Download the app', to: '/download', icon: 'i-lucide-smartphone' },
{
label: 'See how it works',
to: '/how-it-works',
color: 'neutral',
variant: 'subtle',
trailingIcon: 'i-lucide-arrow-right',
},
]
</script>
<template>
<UPageHero
headline="Now on iOS and Android"
title="Build a habit in ten minutes a day"
description="Track streaks, get a nudge at the right time, and see your whole month at a glance."
:links="links"
/>
</template>
headlineis the small line above the title.linksrenders a row ofUButtons under the description. Each object is passed to a button as its props, which is why the array is typedButtonProps[].- The default slot takes an illustration. Add
orientation="horizontal"to put it beside the text.
Everything is themed from the same app.config.ts colours as the rest of your app, so a hero, a pricing table (UPricingPlans) and a dashboard sidebar (UDashboardSidebar) look like one product without extra CSS.
Upgrade Nuxt first, then Nuxt UI
In a Nuxt app, Nuxt UI 4 needs Nuxt 4. The package installs on Nuxt 3, but the module declares Nuxt 4 as its minimum, so Nuxt 3 disables it at startup with an incompatibility warning. Upgrade Nuxt first, with the Nuxt upgrade guide open: Nuxt 4 has changes of its own.
For a Nuxt UI v3 project without Pro, the migration guide has one instruction: update the package. From Nuxt 3, that is two commands:
npx nuxt upgrade --dedupe
npm install @nuxt/ui@latest
nuxt upgrade installs the latest stable Nuxt release, and --dedupe deduplicates the lockfile instead of asking whether to. Skip that line if you are on Nuxt 4 already. In a Pro project, run the first line, then follow the next section instead of the second.
Move a Nuxt UI Pro project to @nuxt/ui
The migration guide gives five mechanical steps for a Pro project. The first swaps the packages:
npm uninstall @nuxt/ui-pro
npm install @nuxt/ui
Then make four edits, in order:
- In
nuxt.config.ts, replace'@nuxt/ui-pro'with'@nuxt/ui'in themodulesarray. - In
app.config.ts, move everything under theuiProkey into theuikey. One package means one theme object. - In your CSS, change
@import "@nuxt/ui-pro"to@import "@nuxt/ui". - Point type imports such as
import type { BannerProps } from '@nuxt/ui-pro'at@nuxt/ui.
The Pro licence key in your environment (NUXT_UI_PRO_LICENSE) can go: version 4 has no licence to check.
With a component override, step 2 gives this app.config.ts. The pageCard override that used to sit under uiPro now sits next to the colours:
export default defineAppConfig({
ui: {
colors: {
primary: 'green',
neutral: 'slate',
},
pageCard: {
slots: {
root: 'rounded-xl',
},
},
},
})
Fix the renamed components and the form changes
Check these changes whichever package you came from. Two components were renamed and one was removed:
UButtonGroupis nowUFieldGroup, a better name for a component that also groups inputs and selects, not only buttons.UPageMarqueeis nowUMarquee.UPageAccordionis removed in favour ofUAccordion. To keep the old look, pass what the Pro version used to set for you:
<UPageAccordion :items="items" />
<UAccordion
:items="items"
:unmount-on-hide="false"
:ui="{ trigger: 'text-base', body: 'text-base text-muted' }"
/>
UAccordion removes a closed item's content from the page by default; :unmount-on-hide="false" keeps it there. The ui classes raise the questions and answers from the default text-sm to text-base and mute the answers' colour.
The v-model modifier nullify on UInput, UInputNumber and UTextarea is renamed nullable: an empty field becomes null. A new optional modifier makes it undefined instead, which is what a Zod schema with .optional() expects. Search for .nullify and nullify: true in model-modifiers.
UForm has two behaviour changes:
- Schema transformations now apply only to the data handed to
@submit. They no longer rewrite the form's state while the user types. - Nested forms must say so. A
UForminside aUFormneeds thenestedprop and anamesuch as`items.${index}`, and it then inherits its state from the parent instead of taking its own:state. If you have a repeating group of fields, this is the change to test first.
The chat components are the one area with a larger migration, because they moved to AI SDK v5: useChat is replaced by the Chat class, messages carry parts instead of content, and reload() is chat.regenerate(). It only applies if you use UChatMessages and friends.
Check the upgrade and decide when to do it
Grep for @nuxt/ui-pro, uiPro, UButtonGroup, UPageMarquee, UPageAccordion and nullify, then start the dev server. For each old component name you missed, Vue prints a "Failed to resolve component" warning in the console and renders an unknown HTML tag instead: a leftover UPageAccordion shows nothing, and the buttons in a leftover UButtonGroup show ungrouped.
Upgrade now if you were paying for Pro: you lose nothing, and the package stops being a separate dependency to keep in step. Upgrade now if you are on v3 and want any of the page or dashboard components. Wait a couple of weeks if your app has deep nested forms or a chat built on the old useChat, and let the first patch releases land before you do the work.
What it means when you are choosing a library
For someone picking a component library for a Nuxt project, the choice got simpler. Before, the free tier covered the controls and the paid tier covered the layouts, so a side project either paid or rebuilt the layouts by hand. Now the whole set is MIT, the templates are real applications you can read to learn how the components fit together, and the Figma kit mirrors the components in code.
The honest limits: it requires Nuxt 4 and Tailwind CSS 4, it is a week old as a major version, and it is a large dependency for a page with two buttons. If you are on Nuxt 4 and building something with pages, forms and a dashboard, it is the default choice. If you are on plain Vue, it works through the Vite plugin, but read the Vue installation page for the differences before committing.