Skip to content

Example eslint config for Nuxt ​

Here you can get a working example for the eslint config file for Nuxt.

🔎 Info

This was used for Nuxt (^3.15.1) and eslint (^0.7.5) (@nuxt/eslint).

If you have not set up your Nuxt project to work with eslint, you can check the setup guide.

Prerequisites ​

Before the example above will work, you need to install some dependencies. Here is the list of what you will need:

1. Install core ESLint and Nuxt-specific configs: ​

console
npm install --save-dev eslint @nuxt/eslint-config @rushstack/eslint-patch

2. Add Vue and TypeScript-specific plugins: ​

console
npm install --save-dev eslint-plugin-vue @vue/eslint-config-typescript @vue/eslint-config-prettier

3. Install TypeScript ESLint plugins: ​

console
npm install --save-dev @typescript-eslint/eslint-plugin @typescript-eslint/parser

This it not explicitly needed, but recommended and also used in the example above.

console
npm install --save-dev eslint-plugin-import eslint-plugin-cypress eslint-config-prettier

Example eslint.config.mjs ​

js
// eslint.config.mjs
import { modernModuleResolution } from '@rushstack/eslint-patch';
modernModuleResolution();

import eslintRecommended from 'eslint/conf/eslint-recommended.js';
import vueEssential from 'eslint-plugin-vue/lib/configs/vue3-essential.js';
import vueTypescript from '@vue/eslint-config-typescript';
import vuePrettier from '@vue/eslint-config-prettier/skip-formatting.js';
import nuxtConfig from '@nuxt/eslint-config';
import cypressRecommended from 'eslint-plugin-cypress/lib/configs/recommended.js';

export default [
    eslintRecommended,
    vueEssential,
    vueTypescript,
    vuePrettier,
    nuxtConfig,
    {
        files: ['cypress/e2e/**/*.{cy,spec}.{js,ts,jsx,tsx}', 'cypress/support/**/*.{js,ts,jsx,tsx}'],
        ...cypressRecommended,
    },
    {
        ignores: [
            '**/.vscode/*',
            '**/*.css',
            '**/*.min.js',
            '**/dist/*',
            '**/licenses/*',
            '**/locale/*',
            '**/misc/*',
            '**/node_modules/*',
            '**/cypress/*',
            '**/patches/*',
            '**/public/*',
            '**/src/assets/*',
            '**/src/vendor/*',
            '**/tests/*',
            'babel.config.js',
            'jest.config.js',
            'postcss.config.js',
            'tailwind.js',
            'vc-trade.ts',
            'vue.config.js',
        ],
    },
    {
        rules: {
            'vue/no-unsupported-features': ['error', { version: '3.3.11', ignores: [] }],
            'import/order': [
                'warn',
                {
                    'newlines-between': 'always',
                    alphabetize: {
                        order: 'asc',
                        caseInsensitive: true,
                    },
                },
            ],
            'import/no-unresolved': 'off',
            '@typescript-eslint/ban-ts-comment': 'warn',
            '@typescript-eslint/ban-types': 'warn',
            '@typescript-eslint/no-empty-interface': 'warn',
            '@typescript-eslint/no-inferrable-types': 'off',
            '@typescript-eslint/no-this-alias': 'warn',
            '@typescript-eslint/no-var-requires': 'warn',
            '@typescript-eslint/explicit-module-boundary-types': 'warn',
            '@typescript-eslint/explicit-function-return-type': [
                'warn',
                {
                    allowTypedFunctionExpressions: false,
                },
            ],
            '@typescript-eslint/no-shadow': ['error'],
            'space-before-function-paren': [
                'error',
                {
                    anonymous: 'never',
                    named: 'never',
                    asyncArrow: 'always',
                },
            ],
            'no-shadow': 'off',
            'getter-return': 'error',
            'max-len': [
                'error',
                200,
                {
                    ignorePattern: 'd="([\\s\\S]*?)"',
                    ignoreTrailingComments: true,
                    ignoreComments: true,
                },
            ],
            'no-console': 'error',
            'no-debugger': 'warn',
            'no-empty': 'error',
            'no-extra-boolean-cast': 'warn',
            'no-inferrable-types': 'off',
            'no-irregular-whitespace': 2,
            'no-prototype-builtins': 'error',
            'no-trailing-spaces': 'error',
            'no-undef': 'warn',
            'prefer-const': 'error',
            'vue/no-dupe-keys': 'warn',
            'prefer-spread': 'warn',
            'no-unreachable': 'warn',
            '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }],
            'no-unused-vars': 'off',
            'no-useless-escape': 'error',
            'no-var': 'error',
            semi: 'error',
            'padding-line-between-statements': [
                'error',
                { blankLine: 'always', prev: '*', next: 'return' },
                { blankLine: 'always', prev: '*', next: 'switch' },
                { blankLine: 'always', prev: '*', next: 'if' },
                { blankLine: 'always', prev: 'block-like', next: '*' },
                { blankLine: 'always', prev: ['const', 'let', 'var'], next: '*' },
                { blankLine: 'any', prev: ['const', 'let', 'var'], next: ['const', 'let', 'var'] },
            ],
            'vue/script-setup-uses-vars': 'error',
            'vue/no-parsing-error': 'error',
            'vue/no-use-v-if-with-v-for': 'error',
            'object-curly-spacing': [2, 'always'],
            'vue/object-curly-spacing': ['error', 'always'],
            'vue/require-v-for-key': 'error',
            'vue/no-multi-spaces': 'error',
            'vue/component-tags-order': [
                'warn',
                {
                    order: [['script', 'template'], 'style'],
                },
            ],
            'vue/padding-line-between-blocks': 'warn',
            'vue/valid-template-root': 'error',
            'vue/valid-v-for': 'warn',
            'vue/valid-v-text': 'error',
            quotes: ['error', 'single'],
            'vue/max-attributes-per-line': [
                'error',
                {
                    singleline: 1,
                    multiline: {
                        max: 1,
                    },
                },
            ],
            'vue/first-attribute-linebreak': [
                'warn',
                {
                    singleline: 'ignore',
                    multiline: 'below',
                },
            ],
            'vue/script-indent': [
                'error',
                2,
                {
                    baseIndent: 1,
                    switchCase: 1,
                },
            ],
            'vue/component-name-in-template-casing': 'warn',
            'vue/multi-word-component-names': 'warn',
            'vue/no-useless-template-attributes': 'warn',
            'vue/html-closing-bracket-newline': [
                'warn',
                {
                    singleline: 'never',
                    multiline: 'never',
                },
            ],
            'vue/html-indent': [
                2,
                2,
                {
                    attribute: 1,
                    baseIndent: 1,
                    closeBracket: 0,
                    alignAttributesVertically: true,
                    ignores: [],
                },
            ],
            'vue/no-required-prop-with-default': ['error', { autofix: false }],
        },
    },
];