Step-by-Step Guide to Setting Up Husky, ESLint, and Prettier in a Next.js TypeScript Project
Tags: nextjs, typescript, husky, eslint
Published: 2024-04-30 18:47:47

### 1. Install Required Packages

First, ensure you have Node.js installed. Initialize your project using:

```bash
npm init -y
# OR
yarn init -y
```

Next, install the necessary packages:

```bash
npm install --save-dev husky lint-staged eslint prettier eslint-config-prettier eslint-plugin-prettier eslint-plugin-unused-imports @typescript-eslint/parser @typescript-eslint/eslint-plugin
# OR
yarn add --dev husky lint-staged eslint prettier eslint-config-prettier eslint-plugin-prettier eslint-plugin-unused-imports @typescript-eslint/parser @typescript-eslint/eslint-plugin
```

### 2. Setup husky

Use the `husky` init command to set up husky in your project:

```bash
npx husky init
```

This command creates a pre-commit script in `.husky/` and updates the prepare script in `package.json`. You can later modify these scripts as per your workflow.

### 3. Setup pre-commit

Create a pre-commit script in `.husky/pre-commit`:

```shell
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npx lint-staged
```

### 4. Setup ESLint

Create an `.eslintrc.json` file in your project's root directory with ESLint configurations:

```json
{
  "$schema": "https://json.schemastore.org/eslintrc.json",
  "env": {
    "browser": false,
    "es2021": true,
    "node": true
  },
  "extends": [
    "plugin:react/recommended",
    "plugin:prettier/recommended",
    "plugin:react-hooks/recommended",
    "plugin:jsx-a11y/recommended",
    "eslint:recommended",
    "plugin:prettier/recommended"
  ],
  "plugins": [
    "react",
    "unused-imports",
    "import",
    "@typescript-eslint",
    "jsx-a11y",
    "prettier"
  ],
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "ecmaFeatures": {
      "jsx": true
    },
    "ecmaVersion": 12,
    "sourceType": "module"
  },
  "settings": {
    "react": {
      "version": "detect"
    }
  },
  "rules": {
    "no-console": "warn",
    "react/prop-types": "off",
    "react/jsx-uses-react": "off",
    "react/react-in-jsx-scope": "off",
    "react-hooks/exhaustive-deps": "off",
    "jsx-a11y/click-events-have-key-events": "warn",
    "jsx-a11y/interactive-supports-focus": "warn",
    "prettier/prettier": "warn",
    "no-unused-vars": "off",
    "unused-imports/no-unused-vars": "off",
    "unused-imports/no-unused-imports": "warn",
    "object-curly-spacing": [
      "error",
      "never"
    ],
    "@typescript-eslint/no-unused-vars": [
      "warn",
      {
        "args": "after-used",
        "ignoreRestSiblings": false,
        "argsIgnorePattern": "^_.*?$"
      }
    ],
    "import/order": [
      "warn",
      {
        "groups": [
          "type",
          "builtin",
          "object",
          "external",
          "internal",
          "parent",
          "sibling",
          "index"
        ],
        "pathGroups": [
          {
            "pattern": "~/**",
            "group": "external",
            "position": "after"
          }
        ],
        "newlines-between": "always"
      }
    ],
    "react/self-closing-comp": "warn",
    "react/jsx-sort-props": [
      "warn",
      {
        "callbacksLast": true,
        "shorthandFirst": true,
        "noSortAlphabetically": false,
        "reservedFirst": true
      }
    ],
    "padding-line-between-statements": [
      "warn",
      {
        "blankLine": "always",
        "prev": "*",
        "next": "return"
      },
      {
        "blankLine": "always",
        "prev": [
          "const",
          "let",
          "var"
        ],
        "next": "*"
      },
      {
        "blankLine": "any",
        "prev": [
          "const",
          "let",
          "var"
        ],
        "next": [
          "const",
          "let",
          "var"
        ]
      }
    ]
  }
}
```

### 5. Setup ESLint Ignore

Create an `.eslintignore` file to ignore specific files from ESLint:

```
.next/*
*.css
dist
esm/*
public/*
tests/*
scripts/*
*.config.js
node_modules
coverage
.next
build
```

### 6. Setup Prettier

Create a `.prettierrc.json` file with Prettier configurations:

```json
{
  "$schema": "https://json.schemastore.org/prettierrc.json",
  "tabWidth": 2,
  "printWidth": 100,
  "semi": true,
  "useTabs": false,
  "singleQuote": false,
  "bracketSpacing": false,
  "endOfLine": "auto",
  "arrowParens": "always",
  "trailingComma": "all"
}
```

### 7. Setup Prettier Ignore

Create a `.prettierignore` file to ignore specific files from Prettier:

```
dist
node_modules
.next
build
scripts
```

### 8. Configure Husky and lint-staged

Update your `package.json` with Husky and lint-staged configurations:

```json
"husky": {
  "hooks": {
    "pre-commit": "lint-staged"
  }
},
"lint-staged": {
  "*.{js,jsx,ts,tsx,json,css,scss,md}": [
    "eslint --fix",
    "prettier --write"
  ]
}
```

### 9. Add Scripts

Optionally, add scripts to your `package.json` for easier usage:

```json
"scripts": {
  "eslint": "eslint . --ext .js,.jsx,.ts,.tsx",
  "format": "prettier --write ."
}
```

Now, you can run `npm run eslint` to check for linting errors and `npm run format` to format your code with Prettier. Before committing your code, Husky will automatically run lint-staged, fixing linting errors and formatting your code.