--- url: https://toolchain.deltabox.studio/guide/config/vite.md --- # Vite+ The whole Vite+ config lives in `toolchain.vite`. Every key is passed through verbatim to Vite+, so `dbx.config.*` stays the only hand-authored root config: ```ts [dbx.config.ts] export default defineConfig({ toolchain: { vite: { test: { include: ['src/**/*.test.ts'], environment: 'node' }, lint: { ignorePatterns: ['dist/**'] }, fmt: { semi: true, singleQuote: true }, }, }, }); ``` `dbx sync` writes a thin root `vite.config.ts` that resolves that config at load time, so the generated file never duplicates (or drifts from) `dbx.config.*`: ```ts [vite.config.ts] import { defineConfig, type ViteUserConfig } from 'vite-plus'; // Generated by @deltabox/toolchain — edit the vite section in dbx.config and run `dbx sync`. import { resolveVite } from '@deltabox/toolchain/vite'; export default defineConfig(resolveVite({ cwd: import.meta.dirname })); ``` The shim imports `defineConfig` from whichever Vite package the project installs (`vite` or `vite-plus`, detected from `package.json`), so a plain `vite` project gets `import { defineConfig, type UserConfig } from 'vite'` and `resolveVite(...)`. `resolveVite(options?)` resolves the **same-directory** `dbx.config.*` (so a nested `vite.config.ts` uses the nested config it sits next to), or the `toolchain` you pass, then returns `toolchain.vite`. Pass `vite` inline to merge overrides over the loaded section (`resolveVite({ vite: { ... } })`). It is exported from `@deltabox/toolchain/vite` for programmatic use too. The single toolchain opt-out is `config`. Set `vite: { config: false }` to leave a hand-written `vite.config.ts` alone; set `config` to a string (relative to the project, or absolute) to write the managed shim at a different path instead. Everything else under `vite` is Vite+ config (plugins, `test`, `lint`, `fmt`, `run.tasks`, ...), so `toolchain.vite` is the full Vite+ configuration. The section is typed as Vite+'s own config (`ToolchainViteConfig` = Vite's `UserConfig` as augmented by Vite+), so the whole Vite+ surface autocompletes in `dbx.config.ts`. ### Static shims By default the shim calls `resolveVite` at load time (`shim: 'runtime'`). Set `vite: { shim: 'static' }` to serialize the resolved config into the shim instead: ```ts [vite.config.ts] import { defineConfig, type ViteUserConfig } from 'vite-plus'; export default defineConfig({ resolve: { tsconfigPaths: true }, run: { tasks: {/* ... */} }, }); ``` A static shim imports only `defineConfig`, so Vite+ can load it without a built `@deltabox/toolchain` (useful for source-first monorepos and bootstrapping). It must stay serializable: functions, regexps and class instances are rejected at sync time (plugins still work with `shim: 'runtime'`). Runtime shims import `@deltabox/toolchain/vite` by default. Set `vite.shimImport` to change that specifier, for example to a local wrapper that re-exports `resolveVite`. Relative values are resolved from the repository root and rewritten relative to each generated config: ```ts [dbx.config.ts] export default defineConfig({ toolchain: { vite: { shimImport: './scripts/local-vite-resolver.ts', }, }, }); ``` This only affects `shim: 'runtime'` (the default); static shims have no toolchain import. Vite 8 resolves TypeScript `paths` through `resolve.tsconfigPaths`. Set it in `toolchain.vite.resolve` (and in Vitest configs) to reuse the tsconfig aliases: ```ts [dbx.config.ts] export default defineConfig({ toolchain: { vite: { resolve: { tsconfigPaths: true } }, }, }); ``` For explicit aliases (or Vite versions without built-in `paths` support), use `resolveTsconfig()` from `@deltabox/toolchain/tsconfig` (see the [tsconfig guide](/guide/tsconfig#resolving-a-tsconfig)). Add the shim to `vite.fmt.ignorePatterns` so Oxfmt leaves the generated file alone - without it `vp fmt` would rewrite the shim and `dbx sync --check` would report drift. In a monorepo put `**/vite.config.ts` on the root config: workspace `fmt` settings are inherited, but a workspace's `ignorePatterns` array replaces the root's list. The default fmt ignores already include `**/vite.config.ts`; `dbx migrate --from vite` adds `/vite.config.ts` to `vite.fmt` only when the folded config already owns `fmt`. ## Format and lint defaults Opt in with `vite: { fmt: true }` / `vite: { lint: true }` to use the toolchain defaults (`DEFAULT_FMT_RULES` / `DEFAULT_LINT_RULES`, exported from `@deltabox/toolchain`). An options object is merged over those defaults, so `fmt: { semi: false }` keeps the shared ignores and print width and only changes `semi`. Shared ignore lists live in `DEFAULT_FMT_IGNORE_PATTERNS` / `DEFAULT_LINT_IGNORE_PATTERNS`, both layered over `DEFAULT_IGNORE_PATTERNS`. All three are exported (readonly) from `@deltabox/toolchain` and `@deltabox/toolchain/shared`, so you can compose your own list instead of repeating the defaults: ```ts [dbx.config.ts] import { DEFAULT_FMT_IGNORE_PATTERNS, defineConfig } from '@deltabox/toolchain'; export default defineConfig({ toolchain: { vite: { fmt: { ignorePatterns: [...DEFAULT_FMT_IGNORE_PATTERNS, '**/fixtures/**'], }, }, }, }); ``` Import sorting is enabled by default too. `sortImports` uses the usual groups (`builtin`, `external`, `internal`/`subpath`, relatives, styles) plus a `workspace` group whose patterns come from every `dbx.config.*` project in the repository, so consumer packages sort together without a hand-written `customGroups` entry. Override `sortImports: false` to disable it, or set your own groups — the resolved workspace group is still appended (and listed in `groups`) unless you disable sorting. To reuse the workspace group in your own `sortImports`, import the resolver: ```ts import { resolveFmtCustomGroups } from '@deltabox/toolchain'; const customGroups = await resolveFmtCustomGroups(); // [{ groupName: 'workspace', elementNamePattern: ['@acme/**', 'app', 'app/**', ...] }] ``` `resolveFmtCustomGroups()` reads the project graph, so it is safe to call from inside `dbx.config.*`. Pass `{ config: 'path/to/dbx.config.ts' }` to resolve a specific config instead of the discovered one, or an inline `project` to add a project the graph does not know about. In VS Code, set `deltabox.toolchain.enableFormatImportGroupDefaults` to `false` (user or workspace settings) to stop the extension from adding the workspace group. ## Oxc config files Vite+ reads `fmt`/`lint` from `vite.config.ts`, but the Oxc VS Code extension reads `.oxfmtrc.json` / `.oxlintrc.json`. When `vite.fmt` / `vite.lint` are defined, `dbx sync` writes those files as managed files so the editor picks up the same configuration. Only the root gets them by default; a nested `dbx.config.*` gets its own pair only when it defines `vite.fmt` / `vite.lint` itself (an inherited root config does not create per-workspace files). To adopt an existing hand-written `vite.config.ts`, fold it in with the migration (see [Migrations](/guide/migrations/#vite-config)): ```sh dbx migrate --from vite --write # folds the object into toolchain.vite (routes fmt/lint) dbx sync # writes the managed vite.config.ts shim ```