Set Up ESLint, Prettier, and Husky for Clean and Consistent Code (2025 Guide)
09/07/2025
This step-by-step guide walks you through setting up ESLint for linting, Prettier for formatting, and Husky for Git hooks. Ensure clean, consistent code and prevent bad commits by automating checks in your JavaScript, TypeScript, or React development workflow.
Set Up ESLint + Prettier + Husky for Clean Code
Automate code quality and formatting in your JavaScript projects!
In collaborative software development, maintaining a consistent code style and ensuring code quality across a team can be a challenge. Manual code reviews for formatting issues are tedious and prone to human error. This is where a powerful trio of tools comes into play: ESLint for code quality, Prettier for consistent formatting, and Husky (with `lint-staged`) for enforcing these standards automatically before every commit.
By setting up these tools, you can automate code hygiene, reduce conflicts, improve readability, and free up your team to focus on building features rather than squabbling over semicolons. Let's dive into how to integrate them into your JavaScript (or TypeScript) project.
Why This Trio?
- ESLint: The Code Quality Guardian
It identifies problematic patterns, potential bugs, and enforces best practices. Think of it as a spell checker for your code logic and structure. - Prettier: The Uncompromising Formatter
It automatically formats your code to a consistent style, eliminating all stylistic debates. It's opinionated, which is its strength ā less configuration, more consistency. - Husky + lint-staged: The Git Hook Enforcers
Husky allows you to easily run scripts at various Git lifecycle events (like `pre-commit`). `lint-staged` ensures that ESLint and Prettier only run on the files you've actually staged for commit, making the process fast and efficient.
Prerequisites
- A JavaScript or TypeScript project.
- Node.js and npm (or yarn) installed.
- Basic familiarity with the command line and `package.json`.
- Git initialized in your project (`git init`).
Step-by-Step Setup Guide
Step 1: Initialize Your Project (if not already)
If you don't have a `package.json` file, create one:
npm init -y
Step 2: Install ESLint
First, install ESLint and initialize its configuration. We'll also install a common config like Airbnb's for a good starting point.
npm install --save-dev eslint @eslint/js eslint-config-airbnb-base eslint-plugin-import
npx eslint --init
When prompted by `npx eslint --init`, choose options that suit your project (e.g., "To check syntax, find problems, and enforce code style", "JavaScript modules (import/export)", "React" if applicable, "None of these" for TypeScript if not using, "Browser" or "Node", "Use a popular style guide", "Airbnb", "JavaScript").
This will create an `.eslintrc.js` (or `.json`, `.yml`) file in your project root. Here's a basic example of what it might look like, adjusted for Prettier later:
// .eslintrc.js
module.exports = {
env: {
browser: true,
es2021: true,
node: true,
},
extends: [
'eslint:recommended',
'airbnb-base', // Or 'airbnb' for React projects
],
parserOptions: {
ecmaVersion: 12,
sourceType: 'module',
},
rules: {
// Custom rules or overrides go here
},
};
Step 3: Install Prettier
Install Prettier as a development dependency:
npm install --save-dev prettier
Create a `.prettierrc.json` file in your project root to define your formatting preferences (optional, Prettier has sensible defaults):
// .prettierrc.json
{
"semi": true,
"singleQuote": true,
"printWidth": 80,
"tabWidth": 2,
"trailingComma": "es5"
}
Step 4: Integrate ESLint and Prettier (Crucial!)
To prevent conflicts between ESLint's style rules and Prettier's formatting, you need to use specific packages:
- `eslint-config-prettier`: Turns off all ESLint rules that are unnecessary or might conflict with Prettier.
- `eslint-plugin-prettier`: Runs Prettier as an ESLint rule, reporting formatting issues as ESLint errors.
npm install --save-dev eslint-config-prettier eslint-plugin-prettier
Now, update your `.eslintrc.js` to extend `plugin:prettier/recommended`. Make sure it's the last item in your `extends` array to ensure it overrides any conflicting rules from previous configs.
// .eslintrc.js (updated)
module.exports = {
env: {
browser: true,
es2021: true,
node: true,
},
extends: [
'eslint:recommended',
'airbnb-base', // or 'airbnb' for React
'plugin:prettier/recommended', // THIS MUST BE THE LAST EXTENSION
],
parserOptions: {
ecmaVersion: 12,
sourceType: 'module',
},
rules: {
// Any custom rules or overrides.
// If you want to enforce Prettier's rules as ESLint errors:
// "prettier/prettier": ["error", { "endOfLine": "auto" }] // Example rule
},
};
Step 5: Install Husky and lint-staged
These tools will set up Git hooks to run our checks automatically.
npm install --save-dev husky lint-staged
npx husky install
`npx husky install` will create a `.husky/` directory and set up the Git hooks.
Step 6: Configure Husky and lint-staged
Add a `pre-commit` hook using Husky and configure `lint-staged` in your `package.json`.
# Add a pre-commit hook that runs lint-staged
npx husky add .husky/pre-commit "npx lint-staged"
Now, add the `lint-staged` configuration to your `package.json`:
// package.json (add this section)
{
"name": "your-project",
"version": "1.0.0",
// ... other existing fields ...
"scripts": {
"lint": "eslint . --ext .js,.jsx,.ts,.tsx",
"lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix",
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,css,md}\"",
"prepare": "husky install" // Add this script for CI/CD environments
},
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
"eslint --fix",
"prettier --write"
],
"*.{json,css,md}": [
"prettier --write"
]
},
"devDependencies": {
// ... your dev dependencies ...
}
}
The `lint-staged` configuration tells Git to run `eslint --fix` and `prettier --write` on staged `.js`, `.jsx`, `.ts`, `.tsx` files, and `prettier --write` on other common file types. The `--fix` flag for ESLint will automatically fix many issues, and `--write` for Prettier will format the files in place.
Step 7: Test Your Setup!
Now, let's see it in action. Make some deliberate formatting and code quality mistakes in one of your JavaScript files (e.g., missing semicolons, inconsistent indentation, an unused variable).
// src/App.js (example of bad code)
import React from 'react';
function App() {
const message = "Hello, world!"
const unusedVar = 123; // Unused variable
console.log(message) // Missing semicolon, bad indentation
return (
<div>
<h1> Welcome!</h1>
</div>
);
}
export default App;
Save the file, then stage it and try to commit:
git add src/App.js
git commit -m "Test: ESLint and Prettier with Husky"
You should see Husky trigger `lint-staged`, which will run ESLint and Prettier. Prettier will automatically reformat the file, and ESLint will fix what it can. If there are unfixable ESLint errors, the commit will be blocked, and you'll see messages in your terminal prompting you to fix them.