BackDev Patterns & Practices
Setup//

Lint-Staged Configuration

Configure lint-staged to run linters and formatters only on staged files, keeping commits fast and code clean with practical examples.

What is lint-staged?

lint-staged runs linters and formatters only on files that are staged for commit. That makes Git hooks fast and avoids running checks on the whole repository.

TL;DR

Configure `lint-staged` to run linters and formatters only on staged files. Combine with Husky to call `npx lint-staged` from a pre-commit hook so commits remain fast and reliable.

Why Use lint-staged?

It significantly reduces the time spent on pre-commit checks by limiting work to the files you changed — making commits fast and developer workflows more efficient.

Example: performance difference

1# Without lint-staged (slow)
2# Checks ALL project files
3npm run lint  # Takes 45 seconds
4
5# With lint-staged (fast)
6# Checks only staged files
7npx lint-staged  # Takes ~2 seconds

Installation

1npm install --save-dev lint-staged

Recommended: install together with Husky and create the pre-commit hook:

1npm install --save-dev husky lint-staged
2npx husky init
3npx husky add .husky/pre-commit "npx lint-staged"

Basic Configuration

Method 1: `package.json`

1{
2  "lint-staged": {
3    "*.{js,ts,jsx,tsx}": [
4      "eslint --fix",
5      "prettier --write"
6    ]
7  }
8}

Method 2: `.lintstagedrc.json`

1{
2  "*.{js,ts,jsx,tsx}": [
3    "eslint --fix",
4    "prettier --write"
5  ],
6  "*.{json,md}": [
7    "prettier --write"
8  ]
9}

Method 3: `lint-staged.config.js`

1module.exports = {
2  '*.{js,ts,jsx,tsx}': [
3    'eslint --fix',
4    'prettier --write',
5  ],
6  '*.{json,md,html,css}': [
7    'prettier --write',
8  ],
9};

Detailed Patterns

Examples for different project types (JS/TS, React, Angular, Full stack).

1{
2  "lint-staged": {
3    "*.{js,ts}": [
4      "eslint --fix --max-warnings=0",
5      "prettier --write"
6    ],
7    "*.{json,md}": [
8      "prettier --write"
9    ]
10  }
11}

Pattern Matching

Use globs to target files precisely.

1{
2  "scripts": {},
3  "lint-staged": {
4    "src/**/*.ts": ["eslint --fix"],
5    "*.{json,md}": ["prettier --write"]
6  }
7}

Commands Explained

`eslint --fix`

Auto-fixes problems in staged files (modifies files).

1eslint --fix

`eslint --fix --max-warnings=0`

Fail if any warnings exist, enforcing a zero-warning policy.

1eslint --fix --max-warnings=0

`prettier --write`

Format staged files in place.

1prettier --write

`jest --bail --findRelatedTests`

Run only tests related to the staged files.

1jest --bail --findRelatedTests

Advanced Configurations

With Type Checking

1module.exports = {
2  '*.{ts,tsx}': [
3    () => 'tsc --noEmit',
4    'eslint --fix',
5    'prettier --write',
6  ],
7};

Conditional Commands

Run tests only if test files changed:

1module.exports = {
2  '*.{ts,tsx}': (filenames) => {
3    const commands = ['eslint --fix', 'prettier --write'];
4    const hasTests = filenames.some(f => f.includes('.test.') || f.includes('.spec.'));
5    if (hasTests) commands.push('jest --bail --findRelatedTests');
6    return commands;
7  }
8};

Integration with Husky

Typical setup uses Husky to call `npx lint-staged` from `.husky/pre-commit`.

1# .husky/pre-commit
2#!/usr/bin/env sh
3. "$(dirname -- "$0")/_/husky.sh"
4
5npx lint-staged

Quick verification

1# Install deps
2pnpm install --save-dev lint-staged husky
3
4# Run lint-staged manually
5npx lint-staged
6
7# Debug mode
8npx lint-staged --debug

Ready For Production

  • Keep `lint-staged` config simple and focused on staged files
  • Ensure pre-commit hook delegates to `npx lint-staged`
  • Document the expected developer workflow (how to fix failures)

Run Manually

1npx lint-staged

Debugging

If you need to inspect what lint-staged is doing, run it in verbose or debug mode and stage a sample file to reproduce the hook locally.

Resources

About

Dev Patterns & Practices is a space for long-form thinking on design, technology, and craft. Every piece is written with care and the belief that the best ideas deserve room to breathe.