Contributing
Thank you for your interest in contributing to Vuetify0! This guide will help you get started.
Getting Started
Before contributing, please:
Read the Getting Started guide to understand the project
Review existing issues↗︎
Join our Discord community↗︎ for questions
Reporting Issues
Bug Reports
When reporting bugs, please include:
A clear, descriptive title
Steps to reproduce the issue
Expected vs actual behavior
Browser and OS information
A minimal reproduction (preferably a Playground link or a repo)
Feature Requests
For new features:
Check if it’s already been requested in issues↗︎
Explain the use case and why it would benefit others
Consider if it fits the headless/composable philosophy↗︎ of Vuetify0
Local Development
Prerequisites
Node 26+ (matches .nvmrc)
pnpm 10.6+
Git
Setup
# Clone the repository
git clone https://github.com/vuetifyjs/0.git
cd 0
# Install dependencies
pnpm install
# Start the dev environment
pnpm dev
# Start the docs site
pnpm dev:docsProject Structure
├── packages/
│ ├── 0/ # @vuetify/v0 - main package
│ │ └── src/
│ │ ├── components/ # Vue components
│ │ ├── composables/ # Composable functions
│ │ ├── utilities/ # Helper functions
│ │ └── types/ # TypeScript types
│ ├── genesis/ # @paper/genesis - design system
│ └── paper/ # @vuetify/paper - styling primitives (dormant, not published)
├── apps/
│ ├── docs/ # Documentation site
│ └── playground/ # Browser-based code editor
└── dev/ # Development environmentUseful Commands
# Development
pnpm dev # Start dev environment
pnpm dev:docs # Start docs site
# Testing
pnpm test # Run tests in watch mode
pnpm test:run # Run tests once
# Type checking
pnpm typecheck # Check all packages
# Linting
pnpm lint # Lint codebase
pnpm lint:fix # Auto-fix lint issues
# Building
pnpm build # Build packagesPull Requests
Branch Model
@vuetify/v0 uses three long-lived branches. Open your PR against the base that matches the semver impact of your change:
| Base | Use it for | Release |
|---|---|---|
master | Bug fixes, docs, chores, refactors, tests | Patch (or no version bump) |
dev | New features that add public API (a component, composable, prop, or option) | Minor |
next | Breaking changes (anything with a BREAKING CHANGE: footer) | Major |
Only master publishes to npm. Work on dev and next merges into master at the next minor or major release, and that merge is what ships it. If you’re unsure which base fits, open against master — a maintainer will retarget it.
::: tip A feat that only touches the docs site, playground, or other tooling (not packages/* source) ships no package version, so it targets master — prefer a docs/chore prefix for those. :::
Before Submitting
Create a new branch from the right base for your change (see Branch Model):
masterfor fixes,devfor features,nextfor breaking changesMake your changes
Write tests for new functionality
Run
pnpm lint:fixto fix formattingRun
pnpm typecheckto check typesRun
pnpm test:runto verify tests passRun
pnpm repo:checkto catch unused files and dependency issuesRun
pnpm changesetif you changedpackages/*source (see Changesets)
The pre-push hook runs lint, typecheck, tests, and repo checks automatically — the steps above keep it green.
Changesets
Releases are managed with Changesets↗︎. If your PR changes published source under packages/*, add a changeset so the change lands in the next release’s version bump and changelog:
pnpm changesetPick the affected package(s), a bump type (patch/minor/major), and a short summary. The command generates a markdown file that you commit alongside your code:
---
"@vuetify/v0": patch
---
fix(createSelection): reject disabled items in multiple-mode applyThe entire changeset body — everything after the frontmatter — is rendered verbatim into the changelog and the GitHub release notes. It is release-note copy, not a commit message. So the rule is not “how long” but “what belongs”:
First line — the conventional-commit summary:
type(Scope): what changed (#PR), describing the change from the consumer’s side, not the diff’s. It stands alone as the whole changeset when it already answers both questions a consumer asks of release notes — does this affect me, and must I act? Many routine fixes need nothing more. A title that instead restates the diff is a commit message wearing changeset frontmatter — that is the failure to avoid, body or not.Body (optional) — add one when the title can’t carry the whole consumer-visible consequence: a behavior delta, a performance change worth quantifying (state the magnitude), a breaking change or migration step, or new public options / escape hatches. Length is earned by consumer impact — a genuinely rich behavior change may run to a paragraph; a routine, self-evident fix stays one line.
Never the mechanism. How you implemented it — internal composables touched, private fields, refactors mirrored from a sibling — belongs in the PR description and the commit body, not the changelog. A consumer reads release notes to decide whether to upgrade and whether they must act, nothing more.
@vuetify/v0 versions and publishes independently; @vuetify/paper is private and unpublished, so it takes no changeset. The @paper/* design systems version separately. Docs-only, chore, refactor, or CI PRs don’t need one. A bot comments on every PR to remind you.
The changeset is how your change reaches a release. On every push to master, automation gathers all pending .changeset/*.md files into a “Version Packages” PR that applies the version bumps and writes the changelog entries. When a maintainer merges that PR, the packages are built, published to npm, and the GitHub releases are created. A packages/* change merged without a changeset still ships in the code — but with no version bump and no changelog entry.
Never edit package.json versions by hand — release automation owns every bump. If you’re unsure which bump type fits, pick your best guess; maintainers adjust it during release review.
PR Guidelines
Keep PRs focused - one feature or fix per PR
Write a clear title and description
Reference any related issues
Be responsive to feedback
Branch Naming
Use descriptive branch names; the prefix should match the base branch you target (see Branch Model):
fix/issue-description- Bug fixes → basemasterfeat/feature-name- New features → basedevdocs/what-changed- Documentation updates → basemasterrefactor/what-changed- Code refactoring → basemaster
Breaking changes target next regardless of prefix.
Commit Messages
Follow the Conventional Commits↗︎ format:
type(scope): subjectTypes
feat- New featurefix- Bug fixdocs- Documentation changesrefactor- Code refactoringtest- Adding or updating testschore- Maintenance tasks
feat and fix are reserved for changes to packages/* source — they drive changelogs and version bumps. Everything else (docs, apps, tooling, CI) uses docs, chore, refactor, or test.
Examples
feat(createSelection): add toggle method
fix(ExpansionPanel): correct aria-expanded state
docs(getting-started): update installation instructions
refactor(createRegistry): simplify reindex logic
test(useForm): add validation edge casesGuidelines
Use imperative mood (“add” not “added”)
Keep the subject under 60 characters
Don’t end with a period
Reference issues when applicable:
fix(useForm): validation error (#123)
Code Style
The sections below are a summary. The design contract behind them — axioms, return-shape conventions, reactivity rules — lives in PHILOSOPHY.md↗︎, with detailed per-scope playbooks in .claude/rules↗︎.
General
Use TypeScript for all new code
Follow existing patterns in the codebase
Prefer
functiondeclarations overconstarrow functionsUse single-word variable names when clear
Add JSDoc comments for public APIs
Composables
Place in
packages/0/src/composables/Each composable in its own directory with
index.tsInclude
@moduleJSDoc block at the topColocate tests as
index.test.tsExport both standalone and context-creation functions
Components
Follow the compound component pattern (Root/Item)
Extend
AtomPropsfor polymorphic componentsUse
useProxyModelfor v-model bindingInclude proper ARIA attributes
Testing
Write tests for new composables and components
Focus on behavior, not implementation details
Test edge cases and error conditions
Use
describeblocks to organize related tests
describe('createSelection', () => {
it('should select an item', () => {
// ...
})
it('should respect mandatory option', () => {
// ...
})
})Skillz Feedback
Vuetify0 Skillz is our interactive tutorial system currently in beta. We’re actively developing new content and improving the learning experience.
How to Give Feedback
Content issues: Typos, unclear instructions, or incorrect examples
Technical problems: Bugs in the interactive editor or validation
Suggestions: New skill ideas or improvements to existing ones
When reporting issues, please include:
The skill name and step number
What you expected vs what happened
Browser and OS information
Thank you for contributing!