vite-plus Documentation

Vite+ is the unified toolchain and entry point for web development. It manages your runtime, package manager, and frontend toolchain in one place.

5,528 stars Rust Rust 1 file ยท ~4,418 tokens
RAW Doc

File: README.md

The Unified Toolchain for the Web
runtime and package management, create, dev, check, test, build, pack, and monorepo task caching in a single dependency


Vite+ is the unified entry point for local web development. It combines Vite, Vitest, Oxlint, Oxfmt, Rolldown, tsdown, and Vite Task into one zero-config toolchain that also manages runtime and package manager workflows:

  • vp env: Manage Node.js globally and per project
  • vp install: Install dependencies with automatic package manager detection
  • vp dev: Run Vite's fast native ESM dev server with instant HMR
  • vp check: Run formatting, linting, and type checks in one command
  • vp test: Run tests through bundled Vitest
  • vp build: Build applications for production with Vite + Rolldown
  • vp run: Run package.json scripts and monorepo tasks with caching and dependency-aware scheduling
  • vp pack: Build libraries for npm publishing or standalone app binaries
  • vp toolchain: Show the versions of Vite+, Vite, Rolldown, Oxc, and other tools
  • vp create / vp migrate: Scaffold new projects and migrate existing ones

All of this is configured from your project root and works across Vite's framework ecosystem.
Vite+ is fully open-source under the MIT license.

Getting Started

Install Vite+ globally as vp:

For Linux or macOS:

bash
curl -fsSL https://vite.plus | bash

For Windows:

bash
irm https://viteplus.dev/install.ps1 | iex

vp handles the full development lifecycle such as package management, development servers, linting, formatting, testing and building for production.

Configuring Vite+

Vite+ can be configured using a single vite.config.ts at the root of your project:

ts
import { defineConfig } from 'vite-plus';

export default defineConfig({
  // Standard Vite configuration for dev/build/preview.
  plugins: [],

  // Vitest configuration.
  test: {
    include: ['src/**/*.test.ts'],
  },

  // Oxlint configuration.
  lint: {
    ignorePatterns: ['dist/**'],
  },

  // Oxfmt configuration.
  fmt: {
    semi: true,
    singleQuote: true,
  },

  // Vite Task configuration.
  run: {
    tasks: {
      'generate:icons': {
        command: 'node scripts/generate-icons.js',
        envs: ['ICON_THEME'],
      },
    },
  },

  // `vp staged` configuration.
  staged: {
    '*': 'vp check --fix',
  },
});

This lets you keep the configuration for your development server, build, test, lint, format, task runner, and staged-file workflow in one place with type-safe config and shared defaults.

Use vp migrate to migrate to Vite+. It merges tool-specific config files such as .oxlintrc*, .oxfmtrc*, and lint-staged config into vite.config.ts.

CLI Workflows (`vp help`)

Start

  • create - Create a new project from a template
  • migrate - Migrate an existing project to Vite+
  • config - Configure hooks and agent integration
  • hooks - Manage the Git hook dispatcher
  • staged - Run linters on staged files
  • install (i) - Install dependencies
  • env - Manage Node.js versions

Develop

  • dev - Run the development server
  • check - Run format, lint, and type checks
  • lint - Lint code
  • fmt - Format code
  • test - Run tests

Execute

  • run - Run monorepo tasks
  • exec - Execute a command from local node_modules/.bin
  • node - Run a Node.js script with the resolved Vite+ environment
  • dlx - Execute a package binary without installing it as a dependency
  • cache - Manage the task cache

Build

  • build - Build for production
  • pack - Build libraries
  • preview - Preview production build

Manage Dependencies

Vite+ automatically wraps your package manager (pnpm, npm, Yarn, or Bun) based on packageManager and lockfiles:

  • add - Add packages to dependencies
  • remove (rm, un, uninstall) - Remove packages from dependencies
  • update (up) - Update packages to latest versions
  • dedupe - Deduplicate dependencies
  • outdated - Check outdated packages
  • list (ls) - List installed packages
  • why (explain) - Show why a package is installed
  • info (view, show) - View package metadata from the registry
  • link (ln) / unlink - Manage local package links
  • rebuild - Rebuild native modules
  • pm - Forward a command to the package manager

Maintain

  • toolchain - Show Vite+ tool versions and their relationships
  • upgrade - Update vp itself to the latest version
  • implode - Remove vp and all related data

Scaffolding your first Vite+ project

Use vp create to create a new project:

bash
vp create

You can run vp create inside of a project to add new apps or libraries to your project.

Organizations can expose a curated set of templates under their npm scope by
publishing @org/create with a createConfig.templates manifest in its package.json.
Once published, vp create @org opens an interactive picker over those
templates, and setting create: { defaultTemplate: '@org' } in
vite.config.ts makes it the default for bare vp create. See the
Organization Templates guide
for the authoring workflow and
create.defaultTemplate for the
config reference.

Migrating an existing project

You can migrate an existing project to Vite+:

bash
vp migrate

GitHub Actions

Use the official setup-vp action to install Vite+ in GitHub Actions:

yaml
- uses: voidzero-dev/setup-vp@<setup-vp-version>
  with:
    node-version: '22'
    cache: true

Set <setup-vp-version> to an exact version from the setup-vp releases page. You can use a commit SHA instead. Do not use the v1 tag. The v1 tag no longer receives updates.

See Automatic Version Updates to configure Dependabot or Renovate.

Manual Installation & Migration

If you are manually migrating a project to Vite+, install these dev dependencies first:

bash
vp install -D vite-plus

Add package-manager overrides so that other packages use the Vite+ versions. Alias vite to @voidzero-dev/vite-plus-core. Pin vitest to the version from vp toolchain vitest. The project and vp test then use the same Vitest copy. Without the pin, a dependency or workspace package can install a different Vitest version. The two versions can use separate mocks, expect functions, and runner states:

json
"overrides": {
  "vite": "npm:@voidzero-dev/vite-plus-core@latest",
  "vitest": "4.1.11"
}

If you are using pnpm, add this to your pnpm-workspace.yaml:

yaml
overrides:
  vite: npm:@voidzero-dev/vite-plus-core@latest
  vitest: 4.1.11

Or, if you are using Yarn:

json
"resolutions": {
  "vite": "npm:@voidzero-dev/vite-plus-core@latest",
  "vitest": "4.1.11"
}

Sponsors

Thanks to namespace.so for powering our CI/CD pipelines with fast, free macOS, Linux, and Windows runners.


File: docs/config/build.md

Build Config

vp dev, vp build, and vp preview use the standard Vite configuration, including plugins, aliases, server, build and preview fields.

Example

ts [vite.config.ts]
import { defineConfig } from 'vite-plus';

export default defineConfig({
  server: {
    port: 3000,
  },
  build: {
    sourcemap: true,
  },
  preview: {
    port: 4173,
  },
});

File: docs/config/check.md

Check Config

vp check runs format, lint, and type checks together. The check block in vite.config.ts sets defaults for the composite command, mirroring the --no-fmt and --no-lint CLI flags.

This is useful when a project wants to keep most of the toolchain but skip one step by default. For example, a team that lints but does not format can disable check.fmt so a plain vp check (the command agents and contributors run most) only lints, without anyone needing to remember --no-fmt.

Example

ts [vite.config.ts]
import { defineConfig } from 'vite-plus';

export default defineConfig({
  check: {
    // Skip the format step in `vp check`. Defaults to true.
    fmt: false,
    // Skip lint rules in `vp check`. Type-check still runs when both
    // `lint.options.typeAware` and `lint.options.typeCheck` are enabled.
    // Defaults to true.
    lint: true,
  },
});

When a step is disabled here, vp check prints a short note: line so it is clear why the step did not run. With the check.fmt: false config above:

bash
$ vp check
note: Format skipped (check.fmt: false in vite.config.ts)
pass: Found no warnings or lint errors in 1 file (12ms, 8 threads)

Scope and precedence

  • These options only affect the composite vp check. Standalone vp fmt and vp lint are unaffected, so you can still run a disabled tool directly when you need it once. Note that any vp check invocation honors these defaults, including one run from a pre-commit hook: if your staged tasks call vp check, that step is skipped there too.
  • A step is skipped if the config disables it or the matching CLI flag is passed. There is no flag to re-enable a step disabled in config; run vp fmt or vp lint directly instead.

File: docs/config/create.md

Create Config

vp create reads the create block in vite.config.ts to set per-repo defaults. See the Creating a Project guide for the full @org template workflow.

`create.defaultTemplate`

When vp create is invoked with no TEMPLATE argument, Vite+ uses this value as if the user had typed it. Typically set to an npm scope whose @scope/create package publishes a createConfig.templates manifest โ€” so bare vp create drops into the org picker.

ts
import { defineConfig } from 'vite-plus';

export default defineConfig({
  create: {
    defaultTemplate: '@your-org',
  },
});

Any value accepted by vp create as a first argument works here: @your-org for an org picker, @your-org:web for a direct manifest entry, vite:application for a built-in, or the name of a local create.templates entry (see below).

`create.templates`

Declare local templates available to vp create inside a monorepo. Each entry is listed in the vp create picker, and selecting it (or passing its name as the template argument) runs the resolved template.

ts
import { defineConfig } from 'vite-plus';

export default defineConfig({
  create: {
    templates: [
      {
        name: 'component',
        template: './tools/create-component',
      },
      { name: 'service', description: 'Backend service', template: 'service-generator' },
    ],
  },
});

Each entry has:

Field Required Notes
name yes Identifier shown in the picker and accepted as vp create <name>. Must be unique within the array. The vite: prefix is reserved for built-in templates.
description yes One-line description shown in the picker.
template yes A workspace package name, a relative ./path to a local package's directory (resolved against the workspace root), a vite:* built-in, a GitHub URL, or a full npm package name (e.g. create-foo). It is run as-is (not shorthand-expanded).

create.templates is the source of truth for local templates: only entries listed here appear in the picker. Vite+ does not infer templates from package.json keywords. A create.templates entry whose template does not match any workspace package, or resolves to a local package without a bin, is reported as an error rather than falling through to an unrelated npm package.

vp create vite:generator adds an entry here automatically (idempotently, preserving defaultTemplate); you can also edit the list by hand.

create.defaultTemplate can name a local entry, so bare vp create opens it directly.

Precedence

CLI argument > create.defaultTemplate > the standard built-in picker.

Explicit specifiers always win, so scripts and CI can bypass the configured default:

bash
# Uses create.defaultTemplate
vp create

# Explicitly ignores the default
vp create vite:library

The org picker also appends a trailing "Vite+ built-in templates" entry โ€” selecting it routes to the vite:monorepo / vite:application / vite:library / vite:generator flow, so built-ins stay reachable interactively even when a default is configured.


File: docs/config/fmt.md

Format Config

vp fmt and vp check read Oxfmt settings from the fmt block in vite.config.ts. See Oxfmt's configuration for details.

Example

ts [vite.config.ts]
import { defineConfig } from 'vite-plus';

export default defineConfig({
  fmt: {
    ignorePatterns: ['dist/**'],
    singleQuote: true,
    semi: true,
    sortPackageJson: true,
  },
});

For package-specific formatting settings in a workspace, use fmt.overrides from the root vite.config.ts.


File: docs/config/index.md

Configuring Vite+

Vite+ keeps project configuration in one place: vite.config.ts, allowing you to consolidate many top-level configuration files in a single file. You can keep using your Vite configuration such as server or build, and add Vite+ blocks for the rest of your workflow:

ts [vite.config.ts]
import { defineConfig } from 'vite-plus';

export default defineConfig({
  server: {},
  build: {},
  preview: {},

  create: {},
  run: {},
  fmt: {},
  lint: {},
  check: {},
  test: {},
  pack: {},
  staged: {},
});

Vite+ Specific Configuration

Vite+ extends the basic Vite configuration with these additions:

  • create for project and template scaffolding defaults
  • run for Vite Task
  • fmt for Oxfmt
  • lint for Oxlint
  • check for vp check defaults
  • test for Vitest
  • pack for tsdown
  • staged for staged-file checks
  • defaultPackage for the default target of bare app commands at a workspace root

defaultPackage

Default target directory for vp dev / vp build / vp preview / vp pack when you invoke them bare in the directory containing the config, an implicit vp -C <dir>:

ts [vite.config.ts]
export default {
  defaultPackage: './frontend',
};

vp reads the values without executing the config, so defaultPackage also works at repository roots with no vite-plus dependency (for example a Laravel or Rails repo whose Vite app lives in frontend/, with vite-plus installed only there). That static read is why the values must stay plain string literals rather than expressions. An explicit -C or positional target always wins over the config.


File: docs/config/lint.md

Lint Config

vp lint and vp check read Oxlint settings from the lint block in vite.config.ts. See Oxlint's configuration for details.

Example

ts [vite.config.ts]
import { defineConfig } from 'vite-plus';

export default defineConfig({
  lint: {
    ignorePatterns: ['dist/**'],
    options: {
      typeAware: true,
      typeCheck: true,
    },
    rules: {
      'no-console': ['error', { allow: ['error'] }],
    },
  },
});

We recommend enabling both options.typeAware and options.typeCheck so vp lint and vp check can use the full type-aware path.

For package-specific lint rules in a workspace, use lint.overrides from the root vite.config.ts.


File: docs/config/pack.md

Pack Config

vp pack reads tsdown settings from the pack block in vite.config.ts. See tsdown's configuration for details.

Example

ts [vite.config.ts]
import { defineConfig } from 'vite-plus';

export default defineConfig({
  pack: {
    dts: true,
    format: ['esm', 'cjs'],
    sourcemap: true,
  },
});