@ver0/oxlint-config
v2.0.2
Published
Oxlint configs used in all ver0 projects
Maintainers
Readme
✨ What's Included
A collection of modular Oxlint configs — the
@ver0/eslint-config counterpart for the VoidZero stack (Vite+,
Oxc). Import only what you need and compose via extends.
- JavaScript — base rules plus
unicorn,import,promiseandoxcplugins - TypeScript — TypeScript rules with type-aware linting
- React — React and hooks rules
- Node.js — Node globals and
nodeplugin rules - Browser — browser globals and restricted globals
- Vitest — test file rules
Every rule is implemented natively in Rust inside the oxlint binary — configs need no plugin dependencies at all.
Rule philosophy
Configs are category-driven: the correctness, suspicious, pedantic and perf categories are enabled
wholesale, so new oxlint rules in those categories roll in automatically with linter updates. The style and
restriction categories are deliberately not enabled — style contains mutually contradictory rules
(no-ternary vs prefer-ternary) and vocabulary policing; instead, a curated set of style and restriction rules is
enabled explicitly. Org-wide opinions are pinned as explicit off entries so they hold even if a consumer enables
more categories.
🚀 Installation
vp add -D @ver0/oxlint-configUnder Vite+ that is all — vp lint ships the linter. Standalone usage additionally requires the oxlint package:
npm install -D oxlint @ver0/oxlint-config📖 Usage
Compose the configs you need in oxlint.config.ts via extends:
// oxlint.config.ts
import {defineConfig} from 'oxlint';
import javascript from '@ver0/oxlint-config/javascript.js';
import typescript from '@ver0/oxlint-config/typescript.js';
import node from '@ver0/oxlint-config/node.js';
import vitest from '@ver0/oxlint-config/vitest.js';
export default defineConfig({
extends: [javascript, typescript, node, vitest],
});In Vite+ projects the same objects go into the lint block of vite.config.ts:
// vite.config.ts
import {defineConfig} from 'vite-plus';
import javascript from '@ver0/oxlint-config/javascript.js';
import node from '@ver0/oxlint-config/node.js';
export default defineConfig({
lint: {
extends: [javascript, node],
},
});Note: shared configs require the TS config format —
.oxlintrc.jsoncannot resolve npm packages inextends.
📦 Available Configs
Each config is a standalone module; oxlint lints JS and TS uniformly, so modules apply to all lintable files (only the vitest module scopes itself to test files). Import to enable, skip to disable — no options, no per-config dependencies.
JavaScript (
javascript.js) — base rules: ESLint core plusunicorn,import,promiseandoxcrules. Always include this one — other configs build on top of it.TypeScript (
typescript.js) —typescriptplugin rules with type-aware linting — see Type-aware linting. Also exportstypescriptUnsafeto disable strictno-unsafe-*type-safety rules:import typescript, {typescriptUnsafe} from '@ver0/oxlint-config/typescript.js'; export default defineConfig({ extends: [typescript, typescriptUnsafe], });React (
react.js) — React and hooks rules. Stylistic JSX rules are intentionally absent — that is oxfmt's job.Node.js (
node.js) — Node.js environment and globals (ESM flavor — CJS globals likerequireand__dirnameare disallowed) plusnodeplugin rules.Browser (
browser.js) — browser environment and globals, restricts confusing globals likeevent,name,locationshadowing.Vitest (
vitest.js) — rules for test and benchmark files (*.test.*,*.benchmark.*).
Type-aware linting
typescript.js turns on typeAware and includes rules that need type information. They require
oxlint-tsgolint:
vp add -D oxlint-tsgolintNot ready for type-aware linting? Disable it in the consuming config:
export default defineConfig({
extends: [javascript, typescript],
options: {typeAware: false},
});🌟 Common Configurations
Node.js API project:
// oxlint.config.ts
import {defineConfig} from 'oxlint';
import javascript from '@ver0/oxlint-config/javascript.js';
import typescript from '@ver0/oxlint-config/typescript.js';
import node from '@ver0/oxlint-config/node.js';
import vitest from '@ver0/oxlint-config/vitest.js';
export default defineConfig({
extends: [javascript, typescript, node, vitest],
});React web application:
// oxlint.config.ts
import {defineConfig} from 'oxlint';
import javascript from '@ver0/oxlint-config/javascript.js';
import typescript from '@ver0/oxlint-config/typescript.js';
import react from '@ver0/oxlint-config/react.js';
import browser from '@ver0/oxlint-config/browser.js';
import vitest from '@ver0/oxlint-config/vitest.js';
export default defineConfig({
extends: [javascript, typescript, react, browser, vitest],
});🔬 Relationship to @ver0/eslint-config
This package covers what oxlint lints natively. The rest stays with
@ver0/eslint-config:
- Svelte — oxlint only lints
<script>blocks of.sveltefiles; template and runes rules needeslint-plugin-svelte - JSON / Markdown — not oxlint's domain
- Formatting — oxfmt replaces Prettier entirely; stylistic lint rules are deliberately absent from these configs
🛠️ Troubleshooting
Rules conflicting with your existing setup? Rules defined next to extends win over the extended configs:
// oxlint.config.ts
import {defineConfig} from 'oxlint';
import javascript from '@ver0/oxlint-config/javascript.js';
import node from '@ver0/oxlint-config/node.js';
export default defineConfig({
extends: [javascript, node],
rules: {
'some-rule': 'off', // Override any rule
},
});Your overrides losing to the presets? oxlint merges a consumer's top-level overrides before the extended
configs, so preset overrides (e.g. vitest's plugin enablement for test files) win. Compose your own overrides as the
last extends entry instead — and note that rules of a plugin enabled only inside an override (like vitest/*) are
silently ignored in your override unless it redeclares the plugin:
// oxlint.config.ts
import {defineConfig} from 'oxlint';
import javascript from '@ver0/oxlint-config/javascript.js';
import vitest from '@ver0/oxlint-config/vitest.js';
export default defineConfig({
extends: [
javascript,
vitest,
{
overrides: [
{
files: ['**/*.test.*'],
plugins: ['vitest'],
rules: {
'vitest/no-disabled-tests': 'off',
},
},
],
},
],
});