JB logo

Command Palette

Search for a command to run...

yOUTUBE
Blog
PreviousNext

Complete Next.js Setup Guide - ESLint, Prettier, Husky & lint-staged Configuration

A comprehensive step-by-step guide to setting up code quality tools in your Next.js TypeScript project with pnpm. Learn how to configure ESLint, Prettier, Husky, and lint-staged for automatic code formatting and linting on every commit. Includes troubleshooting, VS Code integration, and best practices for teams.

Complete Next.js Setup Guide: ESLint, Prettier, Husky & lint-staged

A comprehensive guide for setting up code quality tools in your Next.js TypeScript project with pnpm


📋 Table of Contents

  1. Overview
  2. Prerequisites
  3. What You'll Get
  4. Complete Setup Process
  5. Configuration Files Explained
  6. How It Works
  7. Available Scripts
  8. VS Code Integration
  9. Testing Your Setup
  10. Troubleshooting
  11. Customization Guide
  12. Best Practices

Overview

This setup ensures consistent code quality across your team by automatically:

  • ✅ Formatting code with Prettier
  • ✅ Linting code with ESLint
  • ✅ Fixing issues automatically before commits
  • ✅ Sorting imports consistently
  • ✅ Enforcing TypeScript best practices
  • ✅ Integrating with VS Code for real-time feedback

Prerequisites

Before starting, ensure you have:

  • Node.js 20 or higher
  • pnpm 9 or higher
  • Git initialized in your project
  • Next.js 15+ with TypeScript
  • VS Code (recommended for best experience)

Check your versions:

node --version   # Should be 20 or higher
pnpm --version   # Should be 9 or higher
git --version    # Any recent version

What You'll Get

After completing this setup:

Automatic Code Quality Checks

When you commit code (git commit -m "message"):

  1. Prettier formats your staged files
  2. ESLint checks and auto-fixes issues
  3. Import sorting organizes your imports
  4. Only unfixable errors will block your commit

File Type Coverage

  • JavaScript/TypeScript: .js, .jsx, .ts, .tsx → ESLint + Prettier
  • Styles: .css → Prettier
  • Markdown: .mdx → Prettier
  • Config: .json → Prettier

VS Code Integration

  • Format on save
  • Auto-fix ESLint issues on save
  • Real-time error highlighting
  • Tailwind CSS IntelliSense

Complete Setup Process

Step 1: Create or Navigate to Your Next.js Project

# Create new project (if starting fresh)
pnpm create next-app@latest my-app
# Follow the prompts:
# ✔ Would you like to use TypeScript? › Yes
# ✔ Would you like to use ESLint? › Yes
# (Other options as per your preference)
 
# Navigate to your project
cd my-app

Step 2: Install Required Dependencies

pnpm add -D eslint eslint-config-next prettier husky lint-staged eslint-config-prettier typescript-eslint

What each package does:

  • prettier - Opinionated code formatter
  • eslint-config-prettier - Disables ESLint rules that conflict with Prettier
  • husky - Git hooks manager for running scripts before commits
  • lint-staged - Run linters only on staged Git files

Step 3: Initialize Husky

pnpm exec husky init

This creates:

  • .husky/ folder in your project root
  • A prepare script in your package.json
  • A default pre-commit hook

Step 4: Create Configuration Files

Now create the following files in your project root:

4.1 Create .lintstagedrc.mjs

import path from "path";
 
import { relative } from "path";
 
const buildEslintCommand = (filenames) =>
  `eslint --fix ${filenames
    .map((f) => `"${relative(process.cwd(), f)}"`)
    .join(" ")}`;
 
// eslint-disable-next-line import/no-anonymous-default-export
export default {
  "*.{js,jsx,ts,tsx}": [buildEslintCommand, "prettier --write"],
  "*.{json,css,md}": ["prettier --write"],
};

4.2 Create .prettierrc

{
  "semi": true,
  "tabWidth": 2,
  "printWidth": 80,
  "singleQuote": false,
  "trailingComma": "es5",
  "bracketSpacing": true,
  "endOfLine": "lf",
  "arrowParens": "always"
}

4.3 Create .prettierignore

# Build outputs
.next
.turbo
out
build
dist
 
# Dependencies
node_modules
pnpm-lock.yaml
package-lock.json
yarn.lock
 
# Cache
.cache
.history
*.log
 
# Husky
.husky
 
# Public assets
public
 
# Coverage
coverage
.nyc_output
 
# OS files
.DS_Store
Thumbs.db

4.4 Create eslint.config.mjs

import { defineConfig, globalIgnores } from "eslint/config";
import nextVitals from "eslint-config-next/core-web-vitals";
import nextTs from "eslint-config-next/typescript";
import prettier from "eslint-config-prettier/flat";
 
const eslintConfig = defineConfig([
  ...nextVitals,
  ...nextTs,
  prettier,
  globalIgnores([
    ".next/**",
    "out/**",
    "build/**",
    "next-env.d.ts",
    "node_modules/**",
  ]),
]);
 
export default eslintConfig;

4.5 Create .eslintignore

# Build outputs
.next
.turbo
out
build
dist

# Dependencies
node_modules

# Config files
*.config.js
*.config.mjs
*.config.ts

# Cache
.cache
.eslintcache

# Coverage
coverage
.nyc_output

# Public
public

4.6 Update .husky/pre-commit

Replace the contents of .husky/pre-commit with:

# Run lint-staged on pre-commit
pnpm lint-staged

4.7 Update package.json Scripts

Add these scripts to your package.json:

{
  "scripts": {
    "lint": "eslint .",
    "lint:fix": "eslint . --fix",
    "format": "prettier --write .",
    "prepare": "husky install"
  }
}

Create .vscode/settings.json:

{
  // Editor settings
  "editor.formatOnSave": true,
  "editor.formatOnPaste": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": "explicit",
    "source.organizeImports": "never"
  },
  "editor.quickSuggestions": {
    "strings": "on"
  },
 
  // File associations
  "files.associations": {
    "*.css": "tailwindcss"
  },
 
  // Language-specific formatters
  "[css]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[json]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[javascript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[javascriptreact]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[typescript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[typescriptreact]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[mdx]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[markdown]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
 
  // TypeScript settings
  "typescript.tsdk": "node_modules/typescript/lib",
  "typescript.enablePromptUseWorkspaceTsdk": true,
 
  // ESLint settings
  "eslint.validate": [
    "javascript",
    "javascriptreact",
    "typescript",
    "typescriptreact"
  ]
}

Step 6: Install VS Code Extensions

Install these essential extensions:

# Using VS Code command palette (Ctrl+P / Cmd+P)
ext install dbaeumer.vscode-eslint
ext install esbenp.prettier-vscode
ext install bradlc.vscode-tailwindcss  # If using Tailwind

Or install manually from the VS Code marketplace:

  • ESLint by Microsoft
  • Prettier - Code formatter by Prettier
  • Tailwind CSS IntelliSense by Tailwind Labs (optional)