As a developer, especially when managing code standards, your workflow matters.

You can write great code, but if you:

  • forget to format it before committing,
  • skip linting,
  • or leave vague commit messages like update or fix bug

It all snowballs into a messy codebase that's hard to maintain and collaborate on.

Let me introduce you to three tools that can drastically improve your developer lifecycle:
✅ Husky
✅ lint-staged
✅ commitlint

These tools help enforce discipline and automation without slowing you down, and I've integrated them into my last project.


🔧 What is Husky?

Husky is a tool for managing Git hooks — scripts that run automatically during Git events like pre-commit, commit-msg, pre-push, etc.

Think of it as your personal assistant that runs checks or commands every time you or your teammates interact with Git.

✅ Why Use Husky?

  • Prevent bad code from being committed.
  • Run tests, lint, or format files before commits.
  • Block invalid commits before they reach your repo.

🎯 What is lint-staged?

lint-staged runs linters (or any command) on only the staged files (files that you’re about to commit), not your entire codebase.

✅ Why Use lint-staged?

  • It's super fast.
  • You don’t accidentally commit unformatted or buggy code.
  • It keeps your commits clean and atomic.

📌 Example Use Cases:

  • Run Prettier and ESLint only on changed files.
  • Validate Markdown or config files before committing.

📝 What is commitlint?

commitlint checks if your commit messages meet a defined convention, like Conventional Commits.

✅ Why Use commitlint?

  • Keeps commit messages consistent and meaningful.
  • Useful for changelogs, release automation, and team collaboration.
  • Helps new developers follow the project's commit rules.

🚀 Real-World Setup in My Turborepo Project

I’ve used these tools in my own Turborepo-based MERN monorepo containing:

  • apps/frontend (Next.js)
  • apps/backend (Express.js)
  • apps/extension
  • packages/ui

Let’s walk through how to configure each tool with code examples:


📁 .lintstagedrc Configuration

{
  "apps/backend/**/*.{js,ts}": [
    "prettier --write --config ./apps/backend/.prettierrc.mjs",
    "eslint --max-warnings 0 --config ./apps/backend/eslint.config.mjs"
  ],
  "apps/extension/**/*.{js,jsx,ts,tsx}": [
    "prettier --write --config ./apps/extension/.prettierrc.mjs",
    "eslint --max-warnings 0 --config ./apps/extension/eslint.config.js"
  ],
  "apps/frontend/**/*.{js,jsx,ts,tsx}": [
    "prettier --write --config ./apps/frontend/.prettierrc.mjs",
    "eslint --max-warnings 0 --config ./apps/frontend/eslint.config.js"
  ],
  "packages/ui/**/*.{js,jsx,ts,tsx}": [
    "prettier --write --config ./apps/frontend/.prettierrc.mjs",
    "eslint --max-warnings 0 --config ./apps/frontend/eslint.config.js"
  ],
  "*.md": ["prettier --write"]
}

📁 .commitlintrc.json Configuration

{
  "extends": ["@commitlint/config-conventional"],
  "rules": {
    "type-enum": [
      2,
      "always",
      [
        "ci",
        "chore",
        "docs",
        "feat",
        "fix",
        "perf",
        "refactor",
        "revert",
        "style",
        "assets",
        "test"
      ]
    ]
  }
}

✅ This enforces commit types like feat, fix, docs, chore, etc.

🔴 Invalid: updated code
✅ Valid: feat: add login screen


📁 Husky Git Hooks

You can install and enable Husky with:

pnpm dlx husky install
pnpm pkg set scripts.prepare="husky install"
git add . && git commit -m "chore: setup husky"

husky/pre-commit

npx lint-staged --allow-empty

→ Runs prettier and eslint only on staged files.


husky/commit-msg

npx --no-install commitlint --edit

npx --no-install commitlint --edit


husky/pre-push

npm run test && npm run build

→ Prevents pushing broken builds.


🧠 Summary: Why You Should Use These Tools

Husky

  • What it Does: Hooks into Git to run scripts
  • Why it Matters: Enforces quality and automation at each Git stage

Lint-staged

  • What it Does: Lints only changed files
  • Why it Matters: Keeps commits clean without slowing you down

Commitlint

  • What it Does: Validates commit messages
  • Why it Matters: Ensures consistent commit history for teams & tooling