npm package: @schuijers/eslint-config
Description: Schuijers' ESLint config
Author: Martijn Schuijers
Latest version: 4.0.0

# @schuijers/eslint-config

[![npm][shield-npm]][npm] [![MIT License][shield-license]][license]

My shareable ESLint configs.

- Requires ESLint v9.0.0+.
- Standalone auto-formatting (no Prettier needed).
- Sensible defaults and best practices in a single line.
- Works out of the box with TypeScript, Vue, JSON, YAML, and more.
- Opinionated, yet [fully customizable](#customization).
- Built on [ESLint Flat config](https://eslint.org/docs/latest/use/configure/configuration-files-new) — easy to compose
  and extend.
- Optional [formatters](#formatters) for CSS, HTML, XML, and other languages.
- Style principles: minimal to read, consistent, and diff-stable.
  - Sorted imports and trailing commas
  - Single quotes, no semicolons
  - Uses [ESLint Stylistic](https://github.com/eslint-stylistic/eslint-stylistic)
- Automatically respects your `.gitignore`.

## Installation

```shell script
# npm
npm install --save-dev @schuijers/eslint-config

# yarn
yarn add --dev @schuijers/eslint-config

# pnpm
pnpm add --save-dev @schuijers/eslint-config

# bun
bun add --dev @schuijers/eslint-config
```

This library has a required `peerDependencies` listing for [`eslint`](https://eslint.org/).

## Usage

Create an ESLint [config file](https://eslint.org/docs/latest/use/configure/configuration-files#configuration-file) in
your project root:

```js
// eslint.config.js
import schuijers from '@schuijers/eslint-config'

export default schuijers()
```

## Customization

Normally, you only need to import the `schuijers` preset as described above. You also have the option to configure each
integration individually, for example:

```js
// eslint.config.js
import schuijers from '@schuijers/eslint-config'

export default schuijers({
  // Files and folders to ignore.
  // This will extend the config's default ignores, not override them.
  ignores: [
    '**/fixtures',
    // ...other globs
  ],

  // Automatically parse `.gitignore` to exclude files (enabled by default)
  gitignore: true,

  // Enable support for TypeScript and Vue (autodetected, can also be set explicitly)
  typescript: true,
  vue: true,

  // Disable support for JSONC and YAML files
  jsonc: false,
  yaml: false,
})
```

The `schuijers` factory function can also accept any number of custom config overrides:

```js
// eslint.config.js
import schuijers from '@schuijers/eslint-config'

export default schuijers(
  {
    // Configuration for schuijers's config
  },

  // Additional ESLint flat configs can be added as subsequent arguments.
  // You can provide multiple configs for different file types or overrides.
  {
    files: ['**/*.ts'],
    rules: {},
  },
  {
    rules: {},
  },
)
```

For more advanced usage, you can import individual configs and compose them as needed. We generally don’t recommend this
approach unless you know exactly what each config does, because some options are shared and may require careful
coordination to keep everything consistent.

```js
// eslint.config.js
import {
  combine,
  comments,
  formatters,
  ignores,
  imports,
  javascript,
  jsdoc,
  jsonc,
  node,
  perfectionist,
  stylistic,
  test,
  toml,
  typescript,
  unicorn,
  vue,
  yaml,
} from '@schuijers/eslint-config'

export default combine(
  ignores(),
  javascript(/* options */),
  comments(),
  node(),
  jsdoc(),
  imports(/* options */),
  perfectionist(),
  unicorn(),
  typescript(/* options */),
  stylistic(/* options */),
  test(/* options */),
  vue(/* options */),
  jsonc(),
  yaml(),
  toml(),
  formatters(/* options */),
)
```

Check out the [configs](https://codeberg.org/schuijers/eslint-config/src/branch/main/src/configs) and
[factory](https://codeberg.org/schuijers/eslint-config/src/branch/main/src/factory.ts) for more details.

## Rules overrides

Some rules are only applied to specific file types—for example, `@typescript-eslint/*` rules apply only to `.ts` files,
and `vue/*` rules apply only to `.vue` files. To override rules for specific files, you need to specify the file glob:

```js
// eslint.config.js
import schuijers from '@schuijers/eslint-config'

export default schuijers(
  {
    vue: true,
    typescript: true,
  },
  {
    // Specify the file glob to avoid applying Vue rules to non-Vue files
    files: ['**/*.vue'],
    rules: {
      'vue/operator-linebreak': ['error', 'before'],
    },
  },
  {
    // Rules without `files` apply globally
    rules: {
      '@stylistic/semi': ['error', 'never'],
    },
  }
)
```

Each integration also provides an `overrides` option to make this simpler:

```js
// eslint.config.js
import schuijers from '@schuijers/eslint-config'

export default schuijers({
  vue: {
    overrides: {
      'vue/operator-linebreak': ['error', 'before'],
    },
  },
  typescript: {
    overrides: {
      '@typescript-eslint/consistent-type-definitions': ['error', 'interface'],
    },
  },
  yaml: {
    overrides: {
      // ...
    },
  },
})
```

## Vue

Vue support (including Nuxt or VitePress) is detected automatically if one of these packages is installed in your
project. You can also enable or disable it explicitly:

```js
// eslint.config.js
import schuijers from '@schuijers/eslint-config'

export default schuijers({
  vue: true
})
```

### Vue accessibility

To enable Vue accessibility support, you need to turn it on explicitly:

```js
// eslint.config.js
import schuijers from '@schuijers/eslint-config'

export default schuijers({
  vue: {
    a11y: true
  },
})
```

### Nuxt

Nuxt support is detected automatically if Nuxt is installed in your project. You can also enable it explicitly:

```js
// eslint.config.js
import schuijers from '@schuijers/eslint-config'

export default schuijers({
  vue: {
    nuxt: true
  },
})
```

## Optional Configs

### Formatters

Use external formatters to format files that ESLint cannot handle directly (such as `.css`, `.html`, etc.). This feature
is powered by [`eslint-plugin-format`](https://github.com/antfu/eslint-plugin-format).

```js
// eslint.config.js
import schuijers from '@schuijers/eslint-config'

export default schuijers({
  formatters: {
    /**
     * Format CSS, LESS, SCSS files, including <style> blocks in Vue.
     * Uses Prettier by default.
     */
    css: true,

    /**
     * Format HTML files.
     * Uses Prettier by default.
     */
    html: true,

    /**
     * Format SVG files.
     * Uses Prettier by default.
     */
    svg: true,

    /**
     * Format XML files.
     * Uses Prettier by default.
     */
    xml: true,
  }
})
```

### Typed rules

You can optionally enable [typed rules](https://typescript-eslint.io/linting/typed-linting/) by providing an options
object to the `typescript` config:

```js
// eslint.config.js
import schuijers from '@schuijers/eslint-config'

export default schuijers({
  typescript: {
    tsconfigPath: 'tsconfig.json',
  },
})
```

### Editor-specific disables

Auto-fixing for the following rules is disabled when ESLint is running inside a code editor:

- [`prefer-const`](https://eslint.org/docs/rules/prefer-const)
- [`unused-imports/no-unused-imports`](https://www.npmjs.com/package/eslint-plugin-unused-imports)
- [`vitest/no-focused-tests`](https://github.com/vitest-dev/eslint-plugin-vitest)

This prevents the editor from removing unused imports during refactoring, providing a smoother developer experience. The
rules are still enforced when running ESLint from the terminal.

If you prefer to disable this behavior, set `isInEditor` to `false`:

```js
// eslint.config.js
import schuijers from '@schuijers/eslint-config'

export default schuijers({
  isInEditor: false
})
```

## License

[MIT][license] License &copy; 2025-PRESENT [Martijn Schuijers][me]

[license]: ./LICENSE.md
[me]: https://codeberg.org/schuijers
[npm]: https://npmjs.org/package/@schuijers/eslint-config
[shield-license]: https://img.shields.io/badge/License-MIT-lavender.svg
[shield-npm]: https://img.shields.io/npm/v/@schuijers/eslint-config.svg