🎯 Introduction
Setting up linting and formatting tools for a Next.js 15 project might seem like a Herculean task, but trust me, it’s easier than debugging a missing semicolon in production. 🫠
In this guide, I’ll walk you through configuring ESLint, Prettier, Lint-Staged, and Husky enterprise-style but without the soul-crushing complexity.
If you want clean, consistent code while ensuring no rogue console.log
sneak into your main branch, then this setup is for you. With a streamlined configuration and automated enforcement, you'll catch issues early and maintain high-quality code effortlessly. Let’s dive in. 🚀
⚡ Step 1: Installing Dependencies
Let's kick things off by installing all the necessary dependencies in one swift command because manually installing them one by one is about as fun as debugging on a Friday night. 😵💫
This command sets up ESLint, Prettier, Lint-Staged, Husky, and a few handy plugins to keep your codebase in top shape. Run the following:
npm install --save-dev eslint @eslint/compat @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint-config-next eslint-config-prettier eslint-plugin-import eslint-plugin-prettier eslint-plugin-simple-import-sort eslint-plugin-unicorn husky lint-staged prettier prettier-plugin-tailwindcss
Troubleshooting Installation Issues
If you encounter dependency conflicts or peer dependency errors while running the above command, try installing with the --legacy-peer-deps
flag:
npm install --save-dev --legacy-peer-deps eslint @eslint/compat @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint-config-next eslint-config-prettier eslint-plugin-import eslint-plugin-prettier eslint-plugin-simple-import-sort eslint-plugin-unicorn husky lint-staged prettier prettier-plugin-tailwindcss
This forces npm to ignore strict peer dependency requirements, which can sometimes resolve version conflicts. If the issue persists, consider using npm update
or checking for specific version mismatches. 🚀
🛠️ Step 2: Configuring ESLint
Create a file named eslint.config.mjs
in the root of your project and paste the following code.
This ESLint configuration is designed to enforce best practices, maintain consistent coding styles, and enhance code readability. Feel free to tweak it to fit your project's specific requirements.
import path from "node:path";
import { fileURLToPath } from "node:url";
import { fixupConfigRules } from "@eslint/compat";
import { FlatCompat } from "@eslint/eslintrc";
import js from "@eslint/js";
import typescriptEslintPlugin from "@typescript-eslint/eslint-plugin";
import typescriptEslintParser from "@typescript-eslint/parser";
import simpleImportSort from "eslint-plugin-simple-import-sort";
import unicornPlugin from "eslint-plugin-unicorn";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
allConfig: js.configs.all,
});
const eslintConfig = [
// Extending recommended ESLint configurations
...fixupConfigRules(
compat.extends(
"next/core-web-vitals",
"plugin:import/recommended",
"plugin:prettier/recommended",
),
),
{
// Registering plugins
plugins: {
"simple-import-sort": simpleImportSort,
"@typescript-eslint": typescriptEslintPlugin,
unicorn: unicornPlugin,
},
rules: {
// Sorting imports automatically
"simple-import-sort/exports": "error",
"simple-import-sort/imports": "error",
// Disabling certain unicorn rules that might be too restrictive
"unicorn/no-array-callback-reference": "off",
"unicorn/no-array-for-each": "off",
"unicorn/no-array-reduce": "off",
// Preventing overly strict abbreviation rules
"unicorn/prevent-abbreviations": [
"error",
{
allowList: {
e2e: true,
},
replacements: {
props: false,
ref: false,
params: false,
},
},
],
},
},
{
// TypeScript-specific settings
files: ["**/*.ts", "**/*.tsx"],
languageOptions: {
parser: typescriptEslintParser,
parserOptions: {
project: "./tsconfig.json",
},
},
rules: {
"@typescript-eslint/no-unused-vars": "error",
"@typescript-eslint/no-explicit-any": "warn",
"unicorn/prefer-module": "off",
},
},
{
// JavaScript-specific settings
files: ["**/*.js", "**/*.jsx"],
rules: {
"unicorn/prefer-module": "off",
},
},
];
export default eslintConfig;
🎨 Step 3: Configuring Prettier
Create a prettier.config.js
file and paste this.
This Prettier configuration ensures consistent code formatting, improving readability and reducing unnecessary style debates in your team. Customize it as needed to fit your coding preferences.
module.exports = {
arrowParens: "avoid", // Omit parentheses for single-parameter arrow functions
bracketSameLine: false, // Keep closing brackets on a new line for JSX
bracketSpacing: true, // Ensure spaces between brackets
htmlWhitespaceSensitivity: "css", // Respect CSS for whitespace in HTML
insertPragma: false,
jsxSingleQuote: false, // Use double quotes in JSX
plugins: ["prettier-plugin-tailwindcss"], // Enable Tailwind CSS formatting
printWidth: 80, // Wrap lines at 80 characters for better readability
proseWrap: "always",
quoteProps: "as-needed", // Add quotes only when required
requirePragma: false,
semi: true, // Always use semicolons
singleQuote: false, // Prefer double quotes
tabWidth: 2, // Use 2 spaces per tab
trailingComma: "all", // Use trailing commas where possible
useTabs: false, // Use spaces instead of tabs
};
🔗 Step 4: Configuring Lint-Staged & Husky
Add the following to your package.json
:
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "npx eslint ./src",
"lint:fix": "npm run lint -- --fix",
"format": "prettier . --check",
"format:fix": "prettier . --write",
"type-check": "tsc -b",
"prepare": "husky",
"lint-staged": "lint-staged"
},
"lint-staged": {
"**/*": [
"npm run format:fix",
"npm run lint"
]
}
Now, let's set up a pre-commit hook using Husky:
npx husky init
echo "npm run lint-staged" > .husky/pre-commit
🎉 Conclusion
You now have a battle-hardened, enterprise-grade Next.js linting and formatting setup that will keep your code clean, maintainable, and bug-free! 🏆
🔥 Quick Recap of What We've Done:
- Installed ESLint, Prettier, Lint-Staged, and Husky.
- Configured ESLint with rules that enforce best practices.
- Set up Prettier for consistent code formatting.
- Integrated Lint-Staged to format and lint only staged files.
- Configured Husky to enforce these checks before every commit.
🚀 With This Setup in Place:
- No more accidental linting issues in production.
- Your code is always formatted neatly.
- Pre-commit hooks prevent bad commits.
- Better collaboration and code consistency.
Whether you're working solo or in a team, this setup will help you stay productive and focus on building amazing features without worrying about messy code! 🚀