Husky + Prettier + lint-staged Setup for Next.js
Set up Husky v9, Prettier, and lint-staged in your Next.js project. Step-by-step guide covering pre-commit hooks with the correct 2026 config.
On this page
Most code quality issues are caught too late: in code review, or worse, in production. Husky, Prettier, and lint-staged give you an automatic check on every single commit, right on your machine, before the code ever leaves your editor.
This guide walks through the full setup for a Next.js project using the current versions of all three tools. If you've tried this before with a guide from 2022 and it didn't work, it's probably because Husky changed its configuration format in v9.
- 1
What These Tools Do
Three tools, each with a distinct job. Together they form an automatic quality gate that runs on every commit:
Prettierformats your code automatically. You set the rules once (line length, single vs double quotes, trailing commas) and it handles the rest.lint-stagedruns linters only on the files you've staged for a commit, not your entire codebase. This keeps the pre-commit check fast even on large projects.Huskyconnects everything to Git. It installs scripts that run automatically at key moments: in this setup, immediately before a commit is finalized.
- 2
Install the Tools
From your Next.js project root, install the three dev dependencies. Next.js already ships with ESLint configured, so you don't need to install that separately.
bashnpm install --save-dev prettier husky lint-staged - 3
Configure Prettier
Create a
.prettierrcfile in your project root. These are sensible defaults for a Next.js TypeScript project (adjust them to your team's preference):json{ "semi": true, "singleQuote": true, "trailingComma": "es5", "printWidth": 100, "tabWidth": 2 } - 4
Initialize Husky v9
This is where most guides go wrong. Husky v9 dropped the old
.huskyrcfile format. Run one command to initialize it:bashnpx husky init - 5
Configure the Pre-Commit Hook
Open
.husky/pre-commit(it was just created byhusky init). Replace its contents with a single line that triggerslint-staged:shnpx lint-staged - 6
Configure lint-staged
Add a
lint-stagedkey to yourpackage.json. This tells it which tools to run on which file types when they're staged:json{ "lint-staged": { "*.{js,jsx,ts,tsx}": [ "eslint --fix", "prettier --write" ], "*.{json,css,md}": [ "prettier --write" ] } } - 7
Test the Setup
Stage a file with a formatting issue and try to commit.
lint-stagedwill run both tools automatically:bashgit add . git commit -m "test commit"Here's what each outcome looks like in your terminal:
bash โ Success: Prettier auto-fixed, commit goes throughโ Preparing lint-staged... โ Running tasks for staged files... โ Applying modifications from tasks... โ Cleaning up temporary files... [main abc1234] test commit 1 file changed, 5 insertions(+)bash โ Failure: ESLint error blocks the commitโ Preparing lint-staged... โ Running tasks for staged files... โ eslint --fix: src/app/page.tsx 5:7 error 'myVar' is assigned a value but never used no-unused-vars โ lint-staged failed due to a task error. - 8
Common Issues and Fixes
These are the four most common problems developers hit after setting this up:
Create the pre-push hook for TypeScript checking:
sh โ .husky/pre-pushnpx tsc --noEmit
Frequently Asked Questions
What changed between Husky v8 and v9?
| Husky v8 | Husky v9 | |
|---|---|---|
| Initialize | npx husky install | npx husky init |
| Config file | .huskyrc / husky.config.js | No config file: hooks are plain shell scripts |
| Auto-install | "prepare": "husky install" | "prepare": "husky" (added automatically) |
| Hook format | JSON / JS config | Plain shell script in .husky/ |
How do I skip the pre-commit hook for an emergency commit?
Use the --no-verify flag:
git commit --no-verify -m "emergency fix"Why use lint-staged instead of running ESLint on the whole project?
Running ESLint on a large codebase before every commit gets slow: 10, 20, 30 seconds per commit. lint-staged scopes the run to only the files you've staged, keeping pre-commit checks under a second on most projects.
Should I use Prettier, ESLint, or both?
| ESLint | Prettier | |
|---|---|---|
| Purpose | Code quality (unused vars, type errors, logic bugs) | Formatting (indentation, quotes, line breaks) |
| Auto-fix | Partial (some rules only) | Always (formatting is deterministic) |
| Overlap | None | None |
Run ESLint first, then Prettier. Prettier's formatting pass is the final state committed.
Will Husky hooks run in CI?
By default, yes, but you usually don't want them to. In CI, run lint and type-check directly as explicit steps.
HUSKY=0 npm ciDoes this setup work with Yarn or pnpm?
Yes. Replace npm install --save-dev with yarn add --dev or pnpm add -D. The husky init command and lint-staged config are identical: only the package manager command changes.
Husky v9, Prettier, and lint-staged take about five minutes to set up and save hours of back-and-forth over formatting in code review.
Keep the pre-commit hook fast: format and lint only staged files. Move tsc --noEmit to a pre-push hook where a slower check is acceptable.
Related Articles
How to Use Environment Variables in Next.js (Without Leaking Them to the Browser)
Learn how to use .env files in Next.js correctly. Understand NEXT_PUBLIC_, avoid common mistakes, and set variables in Vercel and Cloudflare.
npm Scripts You're Probably Not Using (But Should Be)
pre/post hooks, cross-env, npm-run-all, argument passing, and built-in variables: the npm script patterns developers Google one at a time, in one place.