How to set up 'Prettier + ESLint + Husky + lint-staged + commitlint' for a NextJS app

Cover image for How to set up 'Prettier + ESLint + Husky + lint-staged + commitlint' for a NextJS app
Avatar of Earvin Li
Earvin Li

Before typing the first line of code of a project, a really important step is to set up 'Prettier + ESLint + Husky + lint-staged + commitlint' ('Biome +Lefthook' seems like a more modern and much faster new way of fulfilling the same task) that helps make sure the codebase follow the same formatting, doesn't have obvious compelling bugs and have aligned commit messages.

FYI, the following instructions might be most suitable for a 'NextJS' app but share common settings/ideas with other frameworks like 'Expo' or even 'Express' though definitely with specific small or big differences and twists.

Prettier

First install 'Prettier' and 'prettier-plugin-tailwindcss' (this plugin lets 'Prettier' have abilities to format your 'Tailwind CSS' code like the order of 'Tailwind CSS' class names as a typical example) as dev dependencies by yarn add --dev prettier prettier-plugin-tailwindcss.

Now run prettier --check to check all formatting issues according to 'Prettier' formatting rules or prettier --write to directly auto correct the issues. You can have prettier --write for your build:local script and prettier --check for build, which helps make sure the code you push to origin is already formatted by 'Prettier'. Check 'Prettier' official doc for CLIs that can specify the directory where 'Prettier' will run or other settings.

Create prettier.config.ts file to use plugin(s), custom rules (this is an interesting discussion related to changing the rules) and do other settings. In order to use 'TypeScript' for the config file, you need 'NodeJS' version >= 22.6.0 with --experimental-strip-types flag or >= 24.3.0 without the flag (but if you deploy on 'Vercel', it only always supports LTS version of 'NodeJS'). Create .prettierignore to ignore files that you don't want 'Prettier' to run on.

Do check'Prettier' rules to use this library well and actually what prettier normally does for your code. Specifically, if you find strange multiple line styled code, this is most probably because of printWidth which is default to 80 by 'Prettier'. You can also use comment(s) to prevent 'Prettier' from formatting certain code.

ESlint

'ESLint'** **helps you find places where your code should/can be changed (to have better performance, follow best practices, stick to certain norms and definitely to fix potential bugs, etc.), but without making some of the changes, your code can still be compiled and run though with things that might not work as well expected. You can find many 'ESLint' configs or plugins from 'NPM'. These are basically the rules you want 'ESLint' to run against and the three severities of these rules (off, warning and error).

Install 'ESLint' as a dev dependency by yarn add --dev eslint. Create eslint.config.ts to let 'ESLint' know how you want it to run. If you use flat configs like eslint.config.ts, you also need to install '@eslint/eslintrc' and '@eslint/js' as dev dependencies to build runnable configs (some say 'ESLint' is becoming complex very quickly just like 'webpack'). In order to use 'TypeScript' for the config file, you need to install 'jiti' as a dev dependency or 'NodeJS' version >= 22.10.0 with --experimental-strip-types flag like 'Prettier'. The official doc also has guide about how to migrate from .eslintrc to flat configs.

If you use 'NextJS' and choose to use 'ESLint' when initializing your project, 'eslint-config-next' will be auto installed and the config file will extend it. Do checkthe official doc about 'NextJS' and 'ESLint', for example, 'eslint-plugin-react' and 'eslint-plugin-react-hooks' are already within eslint-config-next, meaning you don't need to install the two separately. A small tip here is that checking config/plugin source code can guide which other configs or plugins to extend.

If you use 'Tailwind CSS', install 'eslint-plugin-tailwindcss' by yarn add --dev eslint-plugin-tailwindcss and extend it with plugin:tailwindcss/recommended, which really helps use 'Tailwind CSS' better. Till now (07082025), 'eslint-plugin-tailwindcss' still only has a beta version to support 'Tailwind CSS' V4 (the V4 support discussion PR ishere). Checkthe official repo about how to use this beta version and especiallythis issue about how to config to find the 'Tailwind CSS' config file since you can only use a 'CSS' file to config 'Tailwind CSS' V4.

And for 'Prettier', install 'eslint-config-prettier' by yarn add --dev eslint-config-prettier and extend it.

Another big thing is about 'TypeScript', 'ESLint' needs a special parser to run on 'TypeScript' files (without which it can only run on 'JavaScript' files) and needs to know your 'TypeScript' configurations. For 'TypeScript' rules, '@typescript-eslint/eslint-plugin' is a good choice. Install the two by yarn add --dev @typescript-eslint/parser @typescript-eslint/eslint-plugin and configure them accordingly. For '@typescript-eslint/eslint-plugin', actually this plugin not only has one set of rules and configs, you can use just plugin:@typescript-eslint/recommended or plugin:@typescript-eslint/recommended-type-checked (checkthe official doc for their specific differences). And you can let 'ESLint' use these 'TypeScript' configs only for your 'TypeScript' files by modifying your 'ESLint' config file.

Use globalIgnores in 'ESLint' config file to ignore files that you don't want 'ESLint' to run on.

There are many other rule configs and plugins. 'airbnb' rules might be the most famous one and here isan interesting discussion about whether to use them or not. One of the ideas is very enlightening and it's quote here and open to discussions:Try looking at package.json of the libraries you're using and trusting: do they have the airbnb? Most likely no, because it's not standard. 'NextJS' also hastheir understandings about recommended 'ESLint' rules. 'eslint-plugin-jsx-a11y' for accessibility and 'eslint-plugin-import' for file importing can be useful as well but which also really depends how you think of the completeness of your overall linting plan of your project and codebase. A good thing is that adding new rules (like 'eslint-plugin-import' and/or 'eslint-plugin-jsx-a11y') after your codebase has been worked on for a certain time doesn't matter (that much?) and the only issue is you need to fix a lot of places since your database is already very big.

Specially, checkhere for the differences between next lint and eslint.

Husky

'Husky'** **enables to use 'Git' hooks, e.g. pre-commit hook triggers 'lint-staged' to run 'Prettier' and/or 'ESLint' on your staged files for formatting and lint checks before committing them and commit-msg triggers 'commitlint' to check and align your commit messages. Install 'Husky' by yarn add --dev husky and initialize it by npx husky init.

Specially, if you have export NODE_OPTIONS="--experimental-strip-types" flag in pre-commit, scripts in 'lint-staged' will all get this flag, meaning corresponding 'Prettier' and/or 'ESLint' can automatically use .ts file extension for their config files.

lint-staged

'lint-staged' enables libraries like 'Prettier' or 'ESLint' and scripts to run on your staged files. Install 'lint-staged' by yarn add --dev lint-staged. Create a lint-staged.config.ts file to config how 'lint-staged' will run and checkthe official doc for other useful settings.

commitlint

'commitlint' helps check and align your commit messages before committing. Install '@commitlint/cli' and '@commitlint/config-conventional' by yarn add --dev @commitlint/cli @commitlint/config-conventional. Create a commitlint.config.ts file wherecertain commit message rules and other configs can be set up and '@commitlint/config-conventional' is like a 'commitlint' plugin which hasall default or conventional rules already.

Checkthis repo for a working example project.

Comments (0)

Avatar of John Doe
Loading...