@mheob/oxlint-config
v4.0.1
Published
Shared OXLint configuration
Readme
OXLint Config
Opinionated, shared OXLint configuration for my projects.
Install
pnpm add -D @mheob/oxlint-config oxlint oxlint-tsgolintoxlint-tsgolint is a required peer dependency: baseConfig enables type-aware linting, and OXLint does not install the type-aware runtime on its own. See Type-aware linting for what that implies — and how to opt out.
Usage
Create an oxlint.config.ts at the root of your project and extend one or more of the provided configs:
// oxlint.config.ts
import { baseConfig, baseJsConfig } from '@mheob/oxlint-config';
import { defineConfig } from 'oxlint';
export default defineConfig({
extends: [baseConfig, baseJsConfig],
});Combine multiple configs by spreading them into the extends array:
// oxlint.config.ts
import {
baseConfig,
baseJsConfig,
reactConfig,
storybookConfig,
tailwindcssConfig,
} from '@mheob/oxlint-config';
import { defineConfig } from 'oxlint';
export default defineConfig({
extends: [baseConfig, baseJsConfig, reactConfig, storybookConfig, tailwindcssConfig()],
});tailwindcssConfig is a factory function and must be called — see tailwindcssConfig for its options.
Add project-specific rule overrides on top:
// oxlint.config.ts
import { baseConfig, baseJsConfig } from '@mheob/oxlint-config';
import { defineConfig } from 'oxlint';
export default defineConfig({
extends: [baseConfig, baseJsConfig],
rules: {
'typescript/no-explicit-any': 'off',
},
});Available configs
baseConfig
The foundation for all projects. Enables the following OXLint plugins and covers their most important rules:
| Plugin | Scope |
| ------------ | -------------------------------- |
| eslint | General JS/TS best practices |
| typescript | TypeScript-specific rules |
| unicorn | Modern JS idioms and consistency |
| import | Import ordering and correctness |
| jsdoc | JSDoc comment quality |
| node | Node.js safety rules |
| oxc | OXC-native rules |
| promise | Promise and async correctness |
Also ships with file-specific overrides for CLI files, config files, scripts, Markdown code blocks, and Vitest test files (enabling the vitest plugin for spec/test/bench files).
It also turns on type-aware linting — see the next section.
Type-aware linting
baseConfig sets:
options: {
typeAware: true,
typeCheck: true,
}typeAware enables the rules that need type information (no-unsafe-assignment, no-floating-promises, strict-boolean-expressions, prefer-readonly-parameter-types, …). typeCheck additionally reports TypeScript compiler diagnostics through OXLint; it is still marked experimental by OXLint.
Two consequences worth planning for:
- Every linted file needs to belong to a
tsconfig.json. Files outside any project — a*.config.jsat the repo root, standalone scripts — resolve to theerrortype, which produces a burst of falseno-unsafe-*warnings. Either include those files in a tsconfig or exclude them from linting. - Linting is slower, since a TypeScript program is built for the linted files.
To opt out entirely:
// oxlint.config.ts
import { baseConfig } from '@mheob/oxlint-config';
import { defineConfig } from 'oxlint';
export default defineConfig({
extends: [baseConfig],
options: {
typeAware: false,
},
});Required peer dependency:
pnpm add -D oxlint-tsgolintbaseJsConfig
Extends baseConfig with additional rules provided via JS plugins. Should be used alongside baseConfig in most projects:
| JS Plugin | Scope |
| ---------------------- | ------------------------------------------ |
| eslint-plugin-regexp | Regex correctness and optimisation |
| eslint-plugin-jsonc | JSON/JSONC/JSON5 key ordering and validity |
| eslint-plugin-yml | YAML structural correctness |
Includes file-specific overrides:
- JSON files (
*.json,*.json5,*.jsonc) — key sorting, value validation, and structural rules - tsconfig.json — enforces canonical
compilerOptionskey order - YAML files (
*.yaml,*.yml) — block mapping, sequence, and whitespace rules
reactConfig
Extends the base with React-specific rules. Applied to **/*.jsx and **/*.tsx files:
| Plugin / Scope | Description |
| -------------- | ------------------------------------------------------------------------------ |
| jsx-a11y | Accessibility rules for JSX markup |
| react | JSX correctness, file extensions, max JSX depth, only-export-components |
| react-perf | Plugin loaded; rules can be enabled per project |
| typescript | Turns off explicit-function-return-type and explicit-module-boundary-types |
Also relaxes eslint/max-lines-per-function and eslint/max-statements inside .jsx and .tsx files.
All rules come from OXLint's built-in plugins, so no extra peer dependencies are required.
nextJsConfig
Enables OXLint's built-in nextjs plugin for **/*.jsx and **/*.tsx files (all rules as warn): font loading (google-font-display, google-font-preconnect, no-page-custom-font), script handling (inline-script-id, next-script-for-ga, no-sync-scripts, no-before-interactive-script-outside-document), document/head correctness (no-document-import-in-page, no-head-import-in-document, no-duplicate-head, no-title-in-document-head), and common mistakes (no-async-client-component, no-html-link-for-pages, no-img-element, no-typos).
nextJsConfig already extends reactConfig, so listing reactConfig separately is not necessary:
// oxlint.config.ts
import { baseConfig, baseJsConfig, nextJsConfig } from '@mheob/oxlint-config';
import { defineConfig } from 'oxlint';
export default defineConfig({
extends: [baseConfig, baseJsConfig, nextJsConfig],
});storybookConfig
Enables Storybook-specific rules for story files (**/*stories.{js,jsx,ts,tsx}) and .storybook/main.ts:
- Story structure and exports (
default-exports,story-exports) - Interaction best practices (
await-interactions,context-in-play-function) - Naming conventions (
prefer-pascal-case,no-redundant-story-name) - Relaxes
no-console,no-alert, andrules-of-hooksinside story files
Required peer dependency:
pnpm add -D eslint-plugin-storybooktailwindcssConfig
Enforces consistent Tailwind CSS class usage via eslint-plugin-better-tailwindcss:
| Rule | Severity |
| ----------------------------------------------------- | -------- |
| better-tailwindcss/enforce-consistent-class-order | warn |
| better-tailwindcss/enforce-consistent-line-wrapping | warn |
| better-tailwindcss/enforce-canonical-classes | error |
| better-tailwindcss/no-deprecated-classes | warn |
| better-tailwindcss/no-duplicate-classes | warn |
| better-tailwindcss/no-unnecessary-whitespace | warn |
| better-tailwindcss/no-conflicting-classes | error |
| better-tailwindcss/no-unknown-classes | error |
Unlike the other configs, tailwindcssConfig is a function. Call it to configure the Tailwind CSS entry point and the classes that enforce-canonical-classes and no-unknown-classes should ignore:
// oxlint.config.ts
import { baseConfig, baseJsConfig, tailwindcssConfig } from '@mheob/oxlint-config';
import { defineConfig } from 'oxlint';
export default defineConfig({
extends: [
baseConfig,
baseJsConfig,
tailwindcssConfig({
options: { entrypoint: './src/styles/index.css' },
ignoredClasses: ['my-prefix-.+'],
}),
],
});Both arguments are optional — tailwindcssConfig() applies the rules with the plugin defaults.
options is passed through to the better-tailwindcss settings, so every option of eslint-plugin-better-tailwindcss is available (entrypoint, tailwindConfig, tsconfig, cwd, detectComponentClasses, rootFontSize, messageStyle, selectors). The argument type is exported as TailwindcssConfig.
Required peer dependency:
pnpm add -D eslint-plugin-better-tailwindcssEditor integration
VS Code
Install the OXC VS Code extension and add to .vscode/settings.json:
{
"editor.defaultFormatter": "oxc.oxc-vscode",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.oxc": "explicit",
},
}Zed
Add to .zed/settings.json:
{
"lsp": {
"oxc": {
"initialization_options": {
"settings": {
"run": "onSave",
"configPath": "./oxlint.config.ts",
},
},
},
},
}Scripts
Add to your package.json:
{
"scripts": {
"format": "oxfmt",
"format:check": "oxfmt --check",
"lint": "oxlint",
"lint:fix": "oxlint --fix"
}
}