Set Up ESLint, Prettier, and Husky for Clean and Consistent Code (2025 Guide)

09/07/2025

Set Up ESLint, Prettier, and Husky for Clean and Consistent Code (2025 Guide)

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
  },
};
            
Note: The `prettier/prettier` rule is optional. `eslint-config-prettier` already turns off conflicting rules. `eslint-plugin-prettier` *runs* Prettier. If you add `"prettier/prettier": "error"`, ESLint will report formatting differences as errors. This is usually desired for strict enforcement.

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.

Important: The `"prepare": "husky install"` script ensures that Husky is installed automatically when someone runs `npm install` (or `yarn install`) in your project, which is great for team collaboration and CI/CD pipelines.

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.

By implementing ESLint, Prettier, and Husky with `lint-staged`, you've created a robust system that ensures every piece of code committed to your repository meets your team's quality and style standards. This automation saves countless hours, prevents frustrating merge conflicts, and fosters a more enjoyable and efficient development process.

Invest in code quality early, and your future self (and your teammates) will thank you!

Happy Coding! ✨