Skip to content

Instantly share code, notes, and snippets.

@codfish
Last active September 20, 2025 18:34
Show Gist options
  • Save codfish/91ef26f3a56a5c5ca0912aa8c0c5c020 to your computer and use it in GitHub Desktop.
Save codfish/91ef26f3a56a5c5ca0912aa8c0c5c020 to your computer and use it in GitHub Desktop.
Prettier + ESLint + Husky + lint-staged + commitlint

My personal & professional linting setup for JS projects.

  • Modern ESLint v9+ flat config: Uses the new flat configuration format
  • Dynamic feature detection: Automatically configures based on your project's dependencies
  • TypeScript support: Full TypeScript linting with modern typescript-eslint parser and rules
  • React ecosystem: React, React Hooks, and JSX accessibility rules when React is detected
  • Next.js support: Automatically configures Next.js official plugin linting rules when detected
  • Test framework agnostic: Supports Jest and Vitest with automatic detection
  • Testing Library integration: Automatically includes Testing Library rules for test files
  • YAML/YML support: Built-in linting for YAML configuration files
  • Prettier integration: Built-in Prettier configuration with conflict resolution via eslint-config-prettier
  • ESM architecture: Built with ECMAScript modules and full TypeScript typing
  • Docker support: Optional configuration for dockerized applications
  • Blockchain/dApp support: Optional configuration for decentralized applications

To understand more, see https://github.com/codfish/eslint-config.

Installation

npm i -D eslint@9 \
  @codfish/eslint-config@latest \
  prettier@3 \
  prettier-plugin-tailwindcss \
  husky@latest \
  lint-staged@latest \
  doctoc

# Uninstall plugins or presets you don't need to manage anymore, `@codfish/eslint-config` includes them all.
npm uninstall typescript-eslint \
  eslint-config-prettier \
  eslint-plugin-jest \
  eslint-plugin-jsx-a11y \
  eslint-plugin-prettier \
  eslint-plugin-react \
  eslint-plugin-react-hooks \
  eslint-plugin-simple-import-sort \
  eslint-plugin-testing-library \
  eslint-plugin-yml \
  @next/eslint-plugin-next \
  eslint-plugin-next \
  commitlint \
  @commitlint/cli \
  @commitlint/config-conventional

# Initialize husky
npx husky init
echo "npx lint-staged" > .husky/pre-commit

Note

Installing prettier & prettier-plugin-tailwindcss is optional. Remove that if you don't have tailwind in your project or you don't care about formatting non-js files.

Usage

Full usage: https://github.com/codfish/eslint-config#usage

Create an eslint.config.js file in your root. Remove any old eslint configs you might have.

// eslint.config.js
import { defineConfig } from 'eslint/config';
import codfish from '@codfish/eslint-config';
import docker from '@codfish/eslint-config/docker';
import dapp from '@codfish/eslint-config/dapp';

export default defineConfig(
  codfish,
  docker,
  dapp,

  {
    rules: {
      // Optionally relax some rules for your project
      'react/prop-types': 'off',
      'import/prefer-default-export': 'off',
      '@typescript-eslint/explicit-function-return-type': 'warn',
    },
  },
);

Prettier

Note

Prettier is included and runs automatically through ESLint for JavaScript, TypeScript, JSX, and TSX files using the built-in configuration. You don't need to install or configure Prettier separately for basic usage.

Reasons to install prettier separately:

  • Formatting css, md, json, or other non-js files that eslint doesn't format by default.

Full usage: https://github.com/codfish/eslint-config#prettier

import codfish from '@codfish/eslint-config/prettier';

/** @type {import('prettier').Config & import('prettier-plugin-tailwindcss').PluginOptions} */
export default {
  ...codfish,
  plugins: ['prettier-plugin-tailwindcss'],
  tailwindStylesheet: './src/styles/app.css',
  tailwindFunctions: ['clsx'], // optional
};
import codfish from '@codfish/eslint-config';
export default codfish;
{
"scripts": {
"lint": "eslint .",
"fix": "eslint . --fix && npm run format",
"format": "prettier --write \"**/*.{json,css,md}\" --config ./prettier.config.js",
"check": "npm run lint && npm run format -- --check --no-write",
},
"commitlint": {
"extends": [
"./node_modules/@codfish/eslint-config/commitlint.js"
]
},
"lint-staged": {
"*.{json,css}": [
"prettier --write --config ./prettier.config.js"
],
"*.md": [
"prettier --write --config ./prettier.config.js",
"doctoc --title '## Table of Contents'"
]
},
}
import codfishPrettier from '@codfish/eslint-config/prettier';
/** @type {import('prettier').Config & import('prettier-plugin-tailwindcss').PluginOptions} */
export default {
...codfishPrettier,
plugins: ['prettier-plugin-tailwindcss'],
tailwindStylesheet: './src/styles/app.css',
tailwindFunctions: ['clsx'], // optional
};
# .github/workflows/validate.yml
name: Validate
on: pull_request_target
jobs:
quality-checks:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v5
- name: Setup Node.js
uses: actions/setup-node@v5
with:
node-version-file: .nvmrc
- name: Install dependencies
run: npm ci
- name: Validate PR commits with commitlint
run:
npx commitlint --from ${{ github.event.pull_request.base.sha }} --to ${{ github.event.pull_request.head.sha }}
--verbose
- name: Run ESLint & Prettier
run: npm run check
@javdl
Copy link

javdl commented Jan 30, 2020

First of all, thanks for these scripts, love it!

Also, I added an extra install step: npm install -g markdownlint-cli
since this is a gist I could not send you a pull request, see my fork: https://gist.github.com/Joostvanderlaan/55bf4c941fcf9ce80a4c5fd54a6b9e2c

@codfish
Copy link
Author

codfish commented Feb 9, 2020

@Joostvanderlaan thanks so much! My plan was to add markdown lint to cod-scripts eventually so that it didn't have to be separate process to install and use that. I have not had a chance to do that though.

Lately though I've personally had second thoughts about using it at all. I'm still on the fence and working through these thoughts but markdownlint seems to be the least useful and most frustrating of the linting tools in this process. As much as I LOVE linting, we've already got prettier doing a lot of cleanup for us. In theory 90+% of the time it's really not critical to catch these linting errors in markdown. With markdown, if someone wants to use two h1 headers (#) or jump from h2's (##) to h4's (####), who cares as long as it looks nice when it's transformed.

Maybe if you're building docs from markdown or have an entire repo of markdown files you could argue it would be a useful tool to enforce certain things. Anyway, I'm still mulling it over but I'm thinking about removing markdownlint from my linting equation!

Thanks again for the shoutout, I'd be interested to hear your thoughts!

@javdl
Copy link

javdl commented Jul 10, 2020

@codfish you're right, it's a bit frustrating to use it. As for the jump from h2 to h4, I get you, but there's more useful rules as well. For example I like things like https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md003---heading-style so I can have consistency in heading styles when working with a team. Makes the files more easy to read. Same for rules like https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md005---inconsistent-indentation-for-list-items-at-the-same-level

@codfish
Copy link
Author

codfish commented Nov 7, 2020

Note to self: Investigate https://github.com/remarkjs/remark

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment