Skip to content

Configuration ​

Vue Doctor works without configuration.

Put one config file in the project root: vue-doctor.config.ts (or .mts, .js, .mjs, .json), or a vueDoctor key in package.json. Parent directories are never searched.

ts
// vue-doctor.config.ts
import { defineConfig } from "@remylagerweij/vue-doctor";

export default defineConfig({
  extends: ["vue-doctor/recommended"], // or "vue-doctor/strict", "vue-doctor/security"
  rules: {
    "vue-doctor/architecture/no-giant-component": "off",
    "vue-doctor/security/no-unsafe-html-sink": "error",
  },
  ignore: { files: ["src/legacy/**"], rules: ["vue-doctor/correctness/no-prevent-default"] },
  gate: { failOn: "error", scope: "new", minScore: 70 },
  deadCode: true,
});
json
{
  "$schema": "./node_modules/@remylagerweij/vue-doctor/schema/vue-doctor.schema.json",
  "ignore": { "files": ["src/legacy/**"] }
}
  • rules sets a severity ("off", "warn", "error") per rule. Rule IDs are vue-doctor/<category>/<rule>, vue/<rule> and knip/<type> (see Rules); the 1.x forms still work but are deprecated.
  • A rule that documents options takes them next to the severity: ["warn", { ... }] (see Rule options).
  • gate, lint, deadCode, verbose and diff are defaults; command-line flags win.
  • The config is validated: unknown keys and invalid values exit with code 2 and say what is wrong.
  • .ts/.js configs are executed. Use JSON when scanning untrusted code.

Test files ​

Rules about shipped code do not run on test files: Nuxt rendering rules (nuxt-no-window-in-ssr and the other vue-doctor/nuxt/* rules except security-headers and no-secret-in-public-runtime-config), every performance and bundle-size rule, no-direct-dom-manipulation, no-prevent-default, the component-structure rules (no-async-setup-without-suspense, prefer-defineProps-destructure, require-defineprops-types, require-emits-declaration, no-giant-component, no-nested-component-definition), router-no-string-push and server-no-console-in-handler. Each rule's page says whether it checks test files. Security rules always run on them.

A test file is, relative to the project root: *.spec.*, *.test.*, *.cy.* and *.e2e.* scripts (and *.spec.vue / *.test.vue), anything under a test/, tests/, __tests__/, __mocks__/, __fixtures__/, e2e/ or cypress/ directory, and vitest, playwright, cypress and jest config files (including variants such as vitest.component.config.ts).

Nuxt projects ​

Run nuxi prepare (or any nuxi dev/build) before scanning a fresh checkout. Knip reads Nuxt's auto-imports and path aliases from the generated .nuxt/ directory; without it every page, component and composable looks unused. When a Nuxt project has no .nuxt/, Vue Doctor still reports duplicate exports but leaves out unused files, exports and types, and lists the dead-code analyzer as incomplete with a reminder to run nuxi prepare. That partial result is never cached.

Rules read ssr and the ssr of each routeRules entry from nuxt.config (statically: only literal keys and values count), so nuxt-no-window-in-ssr does not report pages that Nuxt never renders on the server.

See the configuration reference for every key. For one-off exceptions prefer inline suppression comments.

Rule options ​

Some rules accept options, listed under "Options" on their rule page. Give them next to the severity, on a single rule ID (not a /* group):

json
{
  "rules": {
    "vue-doctor/server/require-input-validation": ["warn", { "validators": ["parseBody", "parseQuery"] }],
    "vue-doctor/server/auth-missing": ["warn", { "authFunctions": ["ensureAdmin"] }]
  }
}
  • An unknown option name or a value of the wrong type is a config error (exit code 2). Options given to a rule that takes none are ignored with a warning.
  • On Nuxt projects the server rules also learn from the project itself, and receive that as the same options: server/utils functions that read the session and throw a 401/403 become authFunctions, and the session cookie's SameSite from nuxt.config becomes sessionCookieSameSite. Lists you configure are added to what is found; other values you configure win.

Existing linters and formatters ​

Vue Doctor uses its own bundled oxlint and eslint-plugin-vue as internal AST analysis engines for <script> and <template> diagnostics. It checks for security, reactivity, SSR, performance and architectural issues rather than formatting or code style, so both engines run even on projects that use Prettier only, Biome, or no linter at all.

When a project has an ESLint config (eslint.config.*, .eslintrc*, package.json#eslintConfig) or Oxlint config (.oxlintrc.json, oxlint.config.*), Vue Doctor reads it statically (without executing project code) and honours:

  • Template rule options on non-Security vue/* rules, such as "vue/component-name-in-template-casing": ["error", "kebab-case"] or "vue/no-unused-vars": ["warn", { "ignorePattern": "^_" }].
  • Disabled rules ("off" or 0) for non-Security vue/* and vue-doctor/* rules (including rules inside @nuxt/eslint .overrideRules({ ... }) or @antfu/eslint-config vue.overrides).
  • Precedence and security: vue-doctor.config.* always wins over inferred linter settings, and Security, Supply Chain and Server rules can never be disabled by a foreign linter config.

Released under the MIT License.