---
title: "Introduction"
description: "Install @vinicunca/eslint-config, a flat ESLint config that lints and formats JavaScript, TypeScript, Vue and more in one call."
canonical_url: "https://vinicunca.dev/eslint/getting-started"
---
# Introduction

> Install @vinicunca/eslint-config, a flat ESLint config that lints and formats JavaScript, TypeScript, Vue and more in one call.

`@vinicunca/eslint-config` is Vinicunca's shareable [flat config](https://eslint.org/docs/latest/use/configure/configuration-files) for ESLint. It lints **and** formats your code, so you don't need Prettier for JavaScript, TypeScript, Vue, JSON, YAML, TOML or Markdown.

> [!NOTE]
> 
> This config is a fork of [antfu/eslint-config](https://github.com/antfu/eslint-config). Most integrations and plugins come from Anthony Fu's work; this fork changes the code style and some defaults. See [Differences from antfu/eslint-config](https://vinicunca.dev/eslint/guides/differences-from-antfu).

## Features

- **One call**: `vinicuncaESLint()` returns a complete flat config with sensible defaults.
- **Formatting without Prettier**: powered by [ESLint Stylistic](https://eslint.style/), with auto-fix for everything.
- **Code style**: 2-space indent, single quotes, semicolons, `} else {` on one line, braces around every block, parentheses around arrow parameters, trailing commas, sorted imports and exports.
- **Auto-detected**: TypeScript (when `typescript` is installed), Vue (when `vue`, `nuxt`, `vitepress` or `@slidev/cli` is installed) and pnpm workspace rules (when a `pnpm-workspace.yaml` exists).
- **On by default**: JSON, JSONC, JSON5, YAML, TOML, Markdown (including code blocks), test files (via the Vitest plugin), Node.js, JSDoc, regular expressions, [e18e](https://e18e.dev/) modernization rules and [anti-slop rules](https://vinicunca.dev/eslint/configuration/optional-configs#antislop).
- **Opt-in**: [React, Next.js, Svelte, Solid, Astro and UnoCSS](https://vinicunca.dev/eslint/configuration/frameworks), [external formatters](https://vinicunca.dev/eslint/configuration/formatters) for CSS/HTML/XML/GraphQL and [type-aware rules](https://vinicunca.dev/eslint/configuration/typescript).
- **Respects .gitignore** by default.
- Requires ESLint `^10.0.0`. Upgrading from v5? See [Upgrading to v6](https://vinicunca.dev/eslint/guides/migrating#upgrading-from-v5-to-v6).

## Installation

```bash [pnpm]
pnpm add -D eslint @vinicunca/eslint-config
```

```bash [npm]
npm install -D eslint @vinicunca/eslint-config
```

```bash [yarn]
yarn add -D eslint @vinicunca/eslint-config
```

```bash [bun]
bun add -d eslint @vinicunca/eslint-config
```

Framework integrations need their own plugins (for example `eslint-plugin-svelte` for Svelte). When you run ESLint in an interactive terminal, the config asks to install any missing plugin for the options you enabled. Each [framework section](https://vinicunca.dev/eslint/configuration/frameworks) lists the exact packages.

## Usage

Create `eslint.config.js` in your project root:

```js [eslint.config.js]
import { vinicuncaESLint } from '@vinicunca/eslint-config';

export default vinicuncaESLint();
```

> [!TIP]
> 
> `vinicuncaESLint` is a named export; the package has no default export. If your `package.json` does not set `"type": "module"`, name the file `eslint.config.mjs`. You can also write [`eslint.config.ts`](https://eslint.org/docs/latest/use/configure/configuration-files#typescript-configuration-files) for typed options.

Pass options to tune the integrations, and extra flat configs to add your own rules:

```js [eslint.config.js]
import { vinicuncaESLint } from '@vinicunca/eslint-config';

export default vinicuncaESLint(
  {
    type: 'lib',
    ignores: ['**/fixtures'],
    vue: { a11y: true },
  },
  {
    files: ['**/*.ts'],
    rules: {
      'ts/no-explicit-any': 'error',
    },
  },
);
```

See [Configuration](https://vinicunca.dev/eslint/configuration) for how options and extra configs combine, and the [options reference](https://vinicunca.dev/eslint/configuration/options) for every option.

## Scripts

Add lint scripts to `package.json`:

```json [package.json]
{
  "scripts": {
    "lint": "eslint",
    "lint:fix": "eslint --fix"
  }
}
```

Then run them with your package manager:

```bash
pnpm lint
pnpm lint:fix
```

> [!NOTE]
> 
> Use `pnpm eslint` (or `npx eslint`) to run the ESLint binary installed in your project. `pnpx eslint` / `pnpm dlx eslint` downloads a separate copy that can't see your local config dependencies.

## Editor setup

### VS Code

Install the [ESLint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint), then add the following to `.vscode/settings.json`:

```jsonc [.vscode/settings.json]
{
  // Disable the default formatter, use ESLint instead
  "prettier.enable": false,
  "editor.formatOnSave": false,

  // Auto fix on save
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": "explicit",
    "source.organizeImports": "never"
  },

  // Silence the stylistic rules in the editor, but still auto fix them
  "eslint.rules.customizations": [
    { "rule": "style/*", "severity": "off", "fixable": true },
    { "rule": "format/*", "severity": "off", "fixable": true },
    { "rule": "*-indent", "severity": "off", "fixable": true },
    { "rule": "*-spacing", "severity": "off", "fixable": true },
    { "rule": "*-spaces", "severity": "off", "fixable": true },
    { "rule": "*-order", "severity": "off", "fixable": true },
    { "rule": "*-dangle", "severity": "off", "fixable": true },
    { "rule": "*-newline", "severity": "off", "fixable": true },
    { "rule": "*quotes", "severity": "off", "fixable": true },
    { "rule": "*semi", "severity": "off", "fixable": true }
  ],

  // Enable ESLint for all supported languages
  "eslint.validate": [
    "javascript",
    "javascriptreact",
    "typescript",
    "typescriptreact",
    "vue",
    "html",
    "markdown",
    "json",
    "json5",
    "jsonc",
    "yaml",
    "toml",
    "xml",
    "gql",
    "graphql",
    "astro",
    "svelte",
    "css",
    "less",
    "scss",
    "pcss",
    "postcss"
  ]
}
```

`source.organizeImports` is turned off because import sorting is handled by the `perfectionist/sort-imports` rule.

With [nvim-lspconfig](https://github.com/neovim/nvim-lspconfig), enable the ESLint language server for every supported file type and silence stylistic rules while keeping them fixable:

```lua
local customizations = {
  { rule = 'style/*', severity = 'off', fixable = true },
  { rule = 'format/*', severity = 'off', fixable = true },
  { rule = '*-indent', severity = 'off', fixable = true },
  { rule = '*-spacing', severity = 'off', fixable = true },
  { rule = '*-spaces', severity = 'off', fixable = true },
  { rule = '*-order', severity = 'off', fixable = true },
  { rule = '*-dangle', severity = 'off', fixable = true },
  { rule = '*-newline', severity = 'off', fixable = true },
  { rule = '*quotes', severity = 'off', fixable = true },
  { rule = '*semi', severity = 'off', fixable = true },
}

local lspconfig = require('lspconfig')

lspconfig.eslint.setup({
  filetypes = {
    'javascript', 'javascriptreact', 'javascript.jsx',
    'typescript', 'typescriptreact', 'typescript.tsx',
    'vue', 'html', 'markdown', 'json', 'jsonc', 'yaml', 'toml', 'xml',
    'gql', 'graphql', 'astro', 'svelte', 'css', 'less', 'scss', 'pcss', 'postcss',
  },
  settings = {
    rulesCustomizations = customizations,
  },
  -- Fix the buffer before saving
  on_attach = function(client, bufnr)
    vim.api.nvim_create_autocmd('BufWritePre', {
      buffer = bufnr,
      command = 'EslintFixAll',
    })
  end,
})
```

You can also format on save with [conform.nvim](https://github.com/stevearc/conform.nvim), [none-ls](https://github.com/nvimtools/none-ls.nvim) or [nvim-lint](https://github.com/mfussenegger/nvim-lint).

### Editor-specific behavior

The config detects when ESLint runs inside an editor (VS Code, JetBrains IDEs, Vim, Neovim or Zed) and makes three rules non-fixable there, so saving a file doesn't delete code you are still working on:

- [`prefer-const`](https://eslint.org/docs/latest/rules/prefer-const)
- [`unused-imports/no-unused-imports`](https://github.com/sweepline/eslint-plugin-unused-imports)
- `test/no-only-tests`

These rules still report problems (as warnings in the editor), and they are fixed normally when you run ESLint from the terminal, in CI or in a git hook. To turn this behavior off, pass `isInEditor: false`:

```js [eslint.config.js]
import { vinicuncaESLint } from '@vinicunca/eslint-config';

export default vinicuncaESLint({
  isInEditor: false,
});
```

## Git hooks

To lint and fix staged files before every commit, use [lint-staged](https://github.com/lint-staged/lint-staged) with [simple-git-hooks](https://github.com/toplenboren/simple-git-hooks):

```bash [pnpm]
pnpm add -D lint-staged simple-git-hooks
```

```bash [npm]
npm install -D lint-staged simple-git-hooks
```

```bash [yarn]
yarn add -D lint-staged simple-git-hooks
```

```bash [bun]
bun add -d lint-staged simple-git-hooks
```

```json [package.json]
{
  "simple-git-hooks": {
    "pre-commit": "pnpm lint-staged"
  },
  "lint-staged": {
    "*": "eslint --fix"
  }
}
```

Then register the hook once:

```bash
# Activate the hooks
pnpm simple-git-hooks
```

Editor detection is skipped inside git hooks and lint-staged, so every fix is applied on commit.

## Next steps

[**Configuration**](https://vinicunca.dev/eslint/configuration)

Learn how options, extra configs and the composer API fit together.

[**Options reference**](https://vinicunca.dev/eslint/configuration/options)

Every option, with its type and default.

[**Frameworks**](https://vinicunca.dev/eslint/configuration/frameworks)

Enable Vue, React, Next.js, Svelte, Solid, Astro or UnoCSS.

[**Agent skill**](https://vinicunca.dev/.well-known/skills/eslint-config/SKILL.md)

Conventions for AI agents writing code linted by this config.

---

- [GitHub](https://github.com/vinicunca/eslint-config)
- [npm](https://www.npmjs.com/package/@vinicunca/eslint-config)


## Sitemap

See the full [sitemap](https://vinicunca.dev/sitemap.md) for all pages.
