{ "env": { "browser": true, "es6": true }, "extends": [ "airbnb", "airbnb/hooks", "plugin:@typescript-eslint/recommended", "plugin:react/recommended", "plugin:jsx-a11y/recommended", "plugin:@next/next/recommended", "plugin:prettier/recommended", "prettier", "next" ], "parserOptions": { "ecmaVersion": 2015, "sourceType": "module", "project": "./tsconfig.json", "ecmaFeatures": { "tsx": true } }, "plugins": ["import", "jsx-a11y", "react", "react-hooks", "@typescript-eslint", "tailwindcss"], "rules": { "react/function-component-definition": [ 2, { "namedComponents": "arrow-function", "unnamedComponents": "arrow-function" } ], "no-console": "error", "no-magic-numbers": ["error", {}], "react/require-default-props": "off", "@typescript-eslint/no-explicit-any": "error", "react/prop-types": "off", // If you're using TypeScript, prop-types are not needed "@typescript-eslint/explicit-module-boundary-types": "off", // Allows you to skip explicit return types in TypeScript "react/jsx-filename-extension": [1, { "extensions": [".tsx"] }], // Only .tsx files for JSX "import/extensions": [ "error", "ignorePackages", { "js": "never", "jsx": "never", "ts": "never", "tsx": "never" } ], "import/no-unresolved": "off", // TypeScript takes care of this "react/react-in-jsx-scope": "off", // Not needed in Next.js "react/jsx-props-no-spreading": "off", // Allowing spread props "react-hooks/rules-of-hooks": "error", "react-hooks/exhaustive-deps": "warn", "import/prefer-default-export": "off", "react/no-multi-comp": "error", "import/no-extraneous-dependencies": [ "error", { "devDependencies": [ "test.{ts,tsx}", // repos with a single test file "test-*.{ts,tsx}", // repos with multiple top-level test files "**/*{.,_}{test,spec}.{ts,tsx}", // tests where the extension or filename suffix denotes that it is a test "**/jest.config.ts", // jest config "**/jest.setup.ts", // jest setup "**/setupTests.ts", "src/utils/*.{ts,tsx}" ], "optionalDependencies": false, "peerDependencies": false, "packageDir": "./" } ], "indent": ["error", 2, { "SwitchCase": 1 }], "react/jsx-indent": ["error", 2], "react/jsx-indent-props": ["error", 2], "linebreak-style": ["error", "unix"], "semi": ["error", "always"], "no-cond-assign": ["error", "always"], "no-trailing-spaces": ["error"], "tailwindcss/classnames-order": "warn", "tailwindcss/no-custom-classname": "warn", "tailwindcss/no-contradicting-classname": "error", "tailwindcss/enforces-shorthand": [ 1, { "callees": ["twMerge"], "config": "./tailwind.config.ts" } ], "prettier/prettier": "error", "jsx-a11y/label-has-associated-control": [ 2, { "controlComponents": ["Input"], "depth": 3 } ] }, "overrides": [ { // enable the rule specifically for TypeScript files "files": ["*.ts", "*.mts", "*.cts", "*.tsx"], "rules": { "@typescript-eslint/explicit-function-return-type": "error" } }, { // feel free to replace with your preferred file pattern - eg. 'src/**/*Slice.ts' "files": ["src/**/*.slice.ts", "src/**/*.reducers.ts"], // avoid state param assignment "rules": { "no-param-reassign": ["error", { "props": false }] } } ], "settings": { "import/resolver": { "node": { "extensions": [".js", ".jsx", ".ts", ".tsx"] } }, "tailwindcss": { "callees": ["twMerge"], "config": "tailwind.config.ts", "prependCustom": false, "removeDuplicates": true, "whitelist": [] } } }