@vinicunca/eslint-config is Vinicunca's shareable flat config for ESLint. It lints and formats your code, so you don't need Prettier for JavaScript, TypeScript, Vue, JSON, YAML, TOML or Markdown.
Features
- One call:
vinicuncaESLint()returns a complete flat config with sensible defaults. - Formatting without Prettier: powered by ESLint Stylistic, 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
typescriptis installed), Vue (whenvue,nuxt,vitepressor@slidev/cliis installed) and pnpm workspace rules (when apnpm-workspace.yamlexists). - On by default: JSON, JSONC, JSON5, YAML, TOML, Markdown (including code blocks), test files (via the Vitest plugin), Node.js, JSDoc, regular expressions, e18e modernization rules and anti-slop rules.
- Opt-in: React, Next.js, Svelte, Solid, Astro and UnoCSS, external formatters for CSS/HTML/XML/GraphQL and type-aware rules.
- Respects
.gitignoreby default. - Requires ESLint
^10.0.0. Upgrading from v5? See Upgrading to v6.
Installation
pnpm add -D eslint @vinicunca/eslint-config
npm install -D eslint @vinicunca/eslint-config
yarn add -D eslint @vinicunca/eslint-config
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 lists the exact packages.
Usage
Create eslint.config.js in your project root:
import { vinicuncaESLint } from '@vinicunca/eslint-config';
export default vinicuncaESLint();
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 for typed options.Pass options to tune the integrations, and extra flat configs to add your own rules:
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 for how options and extra configs combine, and the options reference for every option.
Scripts
Add lint scripts to package.json:
{
"scripts": {
"lint": "eslint",
"lint:fix": "eslint --fix"
}
}
Then run them with your package manager:
pnpm lint
pnpm lint:fix
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, then add the following to .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, enable the ESLint language server for every supported file type and silence stylistic rules while keeping them fixable:
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, none-ls or 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-constunused-imports/no-unused-importstest/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:
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 with simple-git-hooks:
pnpm add -D lint-staged simple-git-hooks
npm install -D lint-staged simple-git-hooks
yarn add -D lint-staged simple-git-hooks
bun add -d lint-staged simple-git-hooks
{
"simple-git-hooks": {
"pre-commit": "pnpm lint-staged"
},
"lint-staged": {
"*": "eslint --fix"
}
}
Then register the hook once:
# Activate the hooks
pnpm simple-git-hooks
Editor detection is skipped inside git hooks and lint-staged, so every fix is applied on commit.