Context for AI reviewers of this repository. @vuetify/v0 is a Vue 3 library of
headless UI primitives and composables — unstyled, logic-focused building blocks
for design systems. Read this before reviewing a diff; it points at the rules that
govern each area rather than restating them.
Judge a diff in packages/0/src/** against these invariants. Each is a real finding
when violated, not a stylistic preference.
- Headless contract — no styling, CSS, or utility classes in package source. The
library ships logic only; visual concerns belong to consumers. Structural inline
styles a primitive genuinely needs (e.g. positioning) are the only exception.
Theme adapters may emit CSS custom properties and
color-scheme; they must not set element-levelcolor/background/padding. Applying tokens is Paper. - Events belong to components, not composables — composables never attach or
handle DOM events; only components (
.vue) do. Awindow.addEventListenerorel.addEventListenerinside a composable body is a violation. - Type guards over raw comparisons — use
#v0/utilitiesguards:isNull(x)notx === null,isUndefined(x)notx === undefined,isNullOrUndefined(x)notx == null; likewiseisString,isNumber,isArray,isObject,isFunction. - Reactivity conventions —
shallowReffor primitives,reffor objects/arrays,toReffor derived values (the default),computedonly to cache expensive work. - Path alias — import package internals via
#v0/(#v0/utilities,#v0/types,#v0/composables,#v0/constants/globals), never relative paths across the package. - SSR safety — use
IN_BROWSERand theSUPPORTS_*constants from#v0/constants/globalsinstead of hand-writtentypeof window !== 'undefined'checks. - Types — zero
any; preferunknownfor genuine unknowns. Reuse#v0/types(ID,Extensible,MaybeArray,DeepPartial,Activation) before inventing new ones. - Naming — single-word names where possible;
indexnotidx;on<Action>nothandle<Action>(onClick,onSubmit); function declarations overconstarrow functions; no comma-separated declarations (let a = 1, b = 2is wrong). - Vue SFCs —
<script setup lang="ts">(setup before lang); with generics<script lang="ts" setup generic="T">. Props via destructuring with defaults, neverwithDefaults. Template refs viauseTemplateRef. - Reuse before building — a primitive that already exists (selection, validation, registries, virtual scroll, popovers, focus, breakpoints, theming) must be extended or composed, not reimplemented. Flag reinvention.
If a v0 primitive already covers it, use that. If you are about to write native
HTML (<button>) or homemade logic (a setTimeout timer, an overlay/dialog),
stop and use the v0 equivalent instead.
Full inventory: skills/vuetify0/SKILL.md. Architecture:
packages/0/PHILOSOPHY.md. Path-scoped rules: .claude/rules/.
packages/0/PHILOSOPHY.md is the architectural source of truth. Before judging an
architectural or API-shape question, read the relevant section (repo read access is
available at review time):
- §1 Identity — headless, WAI-ARIA-compliant primitives; what v0 is and is not.
- §2 Axioms — the non-negotiable principles the design rests on.
- §3 API shape — return conventions (the trinity pattern), option shapes, naming.
- §4 Reactivity model — ref/shallowRef/toRef/computed rules;
reactive:truescope. - §5 Headless contract — the styling/behavior boundary in detail.
- §6 Registries & context —
createRegistry/createContext, tickets,register/onboard. - §7 Events & lifecycle — where DOM events and lifecycle hooks are allowed to live.
- §8 Types — type-level conventions and the shared type vocabulary.
- §9 Errors & invariants —
V0Error, dev-guard warnings, invariant enforcement. - §10 Anti-patterns appendix — catalogued mistakes; check a suspicious diff here.
- Appendix A — section quick-reference index.
Path-scoped standards. Read the ones matching the touched paths before reviewing:
implementation.md— patterns for allpackages/0/src/**source.composables.md— architecture forpackages/0/src/composables/**.components.md— architecture forpackages/0/src/components/**.testing.md— standards for*.test.tsand*.browser.test.ts.benchmarks.md— standards for*.bench.ts.docs.md— architecture forapps/docs/**pages and examples.new-feature-checklist.md— required files/tables when adding a component or composable.
@vuetify/v0 (headless logic, incl. styling primitives) → design systems → Vuetify 4.
Keep concerns at their layer: styling questions are design-system questions, not v0 questions.
apps/playground is a v0 consumer.
- Node must be 26 (
.nvmrc)./exec-daemon/nodeis an older binary that appears earlier on the default PATH. Login shells and~/.bashrcprepend the nvm Node 26 install. Node 26.0.0 does not ship corepack; pnpm 11.16.0 is installed withnpm install -g pnpm@11.16.0. - Boot starts three Vite servers: docs at
http://127.0.0.1:8000, playground athttp://127.0.0.1:5173, and the Emerald dev app athttp://127.0.0.1:5174. On that app,/is the v0 playground and/emeraldis the design-system shell. - Pass Vite flags with
pnpm exec vite.pnpm <script> -- --hostforwards the--into Vite, which then ignores--hostand--port. *:browsertests need Playwright Chromium (pnpm exec playwright install chromiumandpnpm exec playwright install-deps chromium).- Checks used in CI:
pnpm lint,pnpm typecheck,pnpm test:run --project '!*:browser'. Package build:pnpm build:0.