packages/docs/src/pages/en/blog/announcing-vuetify0-v1.md
I've built Vuetify0 — the framework, its documentation, and everything surrounding it — with one express intent: to take everything I've learned over a decade of building Vuetify and pour it into something that will stand the test of time. The principles and the underlying functionality that drive v0 weren't invented for this release; they were honed over ten years of Vuetify, tested against real applications, and only then extracted into a foundation you can build on directly.
Vuetify0 is 1.0. The release candidate held — the frozen surface shipped through the validation window without a breaking change — and the package is now @vuetify/v0, no tag required. For most projects, 1.0 is the signal that a library is safe to build on. For a framework whose job is to build other frameworks, it means something more precise: the contracts are locked.
🖊️ John Leider • 📅 July 22nd, 2026
<PromotedEntry />I want to be precise about what shipped, because it is easy to read "1.0" as "every component is finished." Not all of them are — and for a meta-framework, that is by design.
Vuetify0 is a headless meta-framework — a logic layer you build UI libraries on top of. Its value is not a catalog of buttons; it is the guarantee that the primitives underneath your buttons will not move. So 1.0 is a promise about the foundation:
useTheme, useStorage, and useBreakpoints plugins, and the structural spine the rest of the library is built from (Tabs, Checkbox, Radio, Switch, the providers, and more) — carry a no-breaking-changes guarantee for the entire 1.x line. Breaking changes wait for a major.preview and graduate onto the frozen foundation one at a time, each on its own milestone rather than gated behind a single number. Stabilizing the engine and its load-bearing components first is exactly the right order for a meta-framework — everything downstream inherits that stability.If you have used Vuetify at any point in the last decade, you have relied on this logic without seeing it — selection, registries, focus management, theming. 1.0 is that logic, extracted, hardened, and frozen, so you can build on it directly.
{ width=100% }
::: info The Maturity Matrix lists the current level for every component, composable, and utility. :::
If this is your first time hearing about it: Vuetify0 (v0) is a headless meta-framework for Vue 3. Logic only, zero styling. You do not install v0 to get a button — you install it to build the button your design system paints.
That distinction is the whole point. Most component libraries hand you finished, opinionated UI and ask you to fight the defaults when they do not fit. Most headless libraries hand you a dozen primitives and leave the rest to you. v0 aims at the layer underneath both: the complete state, accessibility, and behavior of a UI library, exposed as composables and unstyled compound components, with nothing rendered until you say so.
The acid test v0 holds itself to: strip every stylesheet from the page, and the components still work — still manage focus, still enforce selection rules, still announce their state to a screen reader. If styling is load-bearing, it is not headless.
There is no plugin to register and nothing is global. Everything is a tree-shakeable import:
import { createSelection, useBreakpoints } from '@vuetify/v0'
import { Tabs, Dialog } from '@vuetify/v0/components'
Headless is not an excuse to ship less. Every v0 component is WAI-ARIA correct out of the box, SSR-safe by default, and exposes each piece of its state as a data-* attribute so a stylesheet — or a design system — can react to it without touching the logic.
Accessibility does not wait for a locale plugin, either. Every component ships a built-in English aria label through the locale system's ti method — "translate if exists" — which returns a translation when one is registered and falls back to the inline default otherwise:
const label = locale.ti('Button.label') ?? 'Button'
An app with no i18n configured still gets meaningful accessible names (WCAG 4.1.2), with zero locale strings bundled into the runtime. Add a locale plugin later and the same components localize with no code change. That is the pattern throughout v0: correct defaults for the beginner, full control for the framework author.
The release cycle closed with a dedicated accessibility pass — carousel autoplay that pauses on focus (WCAG 2.2.2), aria-current on tree items, explicit group labels on sliders and splitters, and more — so the guarantee holds in the details, not just the headline.
The number that matters is not how many buttons v0 draws — it is how much of the hard logic you never have to write again. At 1.0, v0 ships 40 components, 71 composables, and 24 utilities across fifteen categories, with ten more components already scheduled through v1.5.
Before you write custom logic, the odds are v0 already has the primitive:
| You need | Reach for |
|---|---|
| Single, multi, grouped, or nested selection | createSingle, createSelection, createGroup, createNested |
| Wizard / carousel / step tracking | createStep |
| Form validation with async + dirty tracking | createForm, createValidation |
| Autocomplete / combobox | createCombobox |
| Paginated, virtualized, sortable, filterable data | createPagination, createVirtual, createSortable, createFilter, createDataTable |
| Floating UI — popover, tooltip, menu | usePopover |
| Roving tabindex / virtual focus | useRovingFocus, useVirtualFocus |
| Breakpoints, theme, RTL, locale, storage | useBreakpoints, useTheme, useRtl, useLocale, useStorage |
This is where "meta-framework" stops being marketing. The goal is breadth no point-solution can match — the selection, forms, data, and system primitives that every serious UI library re-implements, written once, tested once, and shared. See how that stacks up against a typical headless library in Beyond a Component Library.
v0 is the bottom of a three-layer stack, and each layer only depends on the one below it:
The clearest proof that the foundation is solid is that we are rebuilding on it ourselves. Vuetify's own internals are being refactored to consume v0 directly — the frozen 1.0 surface is exactly what that work stands on. A decade of Vuetify — 41k+ GitHub stars, millions of monthly downloads, MIT-licensed with nothing gated behind a paid tier — is being rebuilt from this layer up.
The fastest way to understand v0 is to use a composable with nothing rendered. createSelection is a complete multi-selection engine — mandatory rules, batch operations, enrollment — and it does not care whether you ever draw a list:
import { createSelection } from '@vuetify/v0'
const selection = createSelection({ mandatory: true })
const home = selection.register({ value: 'home' })
const search = selection.register({ value: 'search' })
home.select() // ticket self-method — select this item
home.isSelected.value // -> true
selection.selectedIds // -> reactive Set of selected ids
selection.selectedValues.value // -> reactive Set { 'home' }
When you do want UI, the same logic backs a headless compound component. The root owns state; the sub-components read it through context — no prop-drilling between siblings:
<script setup lang="ts">
import { Tabs } from '@vuetify/v0/components'
import { shallowRef } from 'vue'
const active = shallowRef('overview')
</script>
<template>
<Tabs.Root v-model="active">
<Tabs.List>
<Tabs.Item value="overview">Overview</Tabs.Item>
<Tabs.Item value="details">Details</Tabs.Item>
</Tabs.List>
<Tabs.Panel value="overview">Overview content</Tabs.Panel>
<Tabs.Panel value="details">Details content</Tabs.Panel>
</Tabs.Root>
</template>
Both examples run live in the docs — createSelection and Tabs — and every example on the site is a multi-file, copy-paste recipe you can open in the playground.
Where it gets interesting is at application scale. DevKey, a developer API dashboard, is the reference implementation — maintained in lockstep with every release. Its dashboard is almost entirely wiring: a Tabs view over a data layer that is useStorage and nothing more, driving the components that render it.
{ width=100% }
The code behind that view is mostly this:
<script setup lang="ts">
import { shallowRef } from 'vue'
import { useNotifications } from '@vuetify/v0'
import { useKeys } from './composables/useKeys' // useStorage-backed CRUD
const tab = shallowRef('keys')
const keys = useKeys() // add / remove / rotate, persisted
const notifications = useNotifications()
const createOpen = shallowRef(false)
function onRotate (id: string) {
keys.rotate(id)
notifications.send({ subject: 'API key rotated', severity: 'success' })
}
</script>
<template>
<DkTabs v-model="tab" :items="[{ value: 'keys', label: 'API Keys' }, /* ... */]">
<template #keys>
<DkTable :items="keys.all.value" @rotate="onRotate" @revoke="keys.removeMany" />
</template>
</DkTabs>
<DkCreateKeyDialog v-model="createOpen" />
</template>
The stable spine here — Tabs and the useStorage-backed data layer — is exactly what 1.0 freezes. The components it orchestrates (DkTable, the create-key dialog, the command palette) are built on preview primitives today; the data-table components promote to stable in v1.1, and the rest follow across the 1.x line. The wiring above doesn't change when they do. Build it yourself with the DevKey integration guide.
The 1.x guarantee is only worth as much as the testing behind it. Heading into 1.0:
mergeDeep, for instance, clears 1.7M+ ops/sec on a shallow merge, and a recent rewrite cut large-grid sort time by roughly 28×. The benchmarks page documents the methodology and per-primitive results.v0 is also built to be understood by the tools people now build with: every documentation page has an Ask AI option, the docs publish llms.txt and llms-full.txt, and the Vuetify MCP server wires the full API reference into your editor.
1.0 locks the engine. Everything on the roadmap from here is components promoting onto that stable foundation — and because the logic already shipped and is already frozen, each one is assembly over a proven primitive, not a rewrite. The milestones are public:
createDataTable and createDataGrid, plus the Alert componentcreateVirtual, createKanban, and createOtpBeyond the components, the first design systems — Emerald and Onyx — come next, and the whole surface is authored for forward-compatibility with Vue Vapor. Track it on the roadmap and the milestones.
pnpm install @vuetify/v0
No plugin to register, nothing global. Import what you need:
import { createSelection } from '@vuetify/v0'
import { Dialog } from '@vuetify/v0/components'
The getting-started guide covers setup, and Vuetify0 Skillz walks through the docs, search, and examples interactively.
The spine is. Thirteen components — the structural and selection primitives the rest of the library builds on, like Tabs, Checkbox, Radio, and Switch — are stable and semver-locked at 1.0, alongside nineteen composables and seventeen utilities. The remaining components are preview and promote individually as they meet the bar. For a meta-framework, the engine and its load-bearing components are what must not move first; everything downstream inherits that stability.
Yes. Code written against the beta API ran through six beta releases, the release candidate, and into 1.0 without changes, and the surface freeze is enforced by CI on every pull request. The stable set will not break under you within 1.x.
Yes. They do not conflict, and you can adopt v0 primitives inside a Vuetify 4 app today. Vuetify's own internals are being refactored to consume v0 directly.
Each is plotted on the public milestones: table components in v1.1, tours in v1.2, virtualized lists, Kanban, and OTP in v1.3, then time and date pickers in v1.4 and v1.5. Each promotes when it is ready.
Bug reports go through issues.vuetifyjs.com. The contributing guide covers local setup, and Discord is the place to discuss before you build.
Vuetify0 is part of the Vuetify ecosystem. Documentation is at 0.vuetifyjs.com; source is on GitHub.