@leaflink/eslint-config
Configuration for ESLint, Prettier, Stylelint, and Commitlint at LeafLink.

Features
Installation
[!IMPORTANT]
Requirements
ESLint v9 and above
Node.js v20 and above
Stylelint v16 and above (optional)
If you're going to be using both eslint & stylelint in your project, then the fastest way to get started is to run:
npx install-peerdeps --dev @leaflink/eslint-config
If you don't need to leverage stylelint in your project, then just install this package along with eslint v9:
npm install --save-dev eslint@9 @leaflink/eslint-config@latest
If you want to manually install all peer dependencies without using install-peerdeps
, you can run:
npm install --save-dev eslint@9 @leaflink/eslint-config@latest stylelint@16 stylelint-config-standard-scss stylelint-config-standard-vue stylelint-order postcss-html
Migration to v4 (ESLint v9+, Stylelint v16+, Node v20+)
- Migrate your app to Node 20 or greater.
npm uninstall eslint-config-leaflink stylelint stylelint-config-standard-scss stylelint-config-standard-vue
.npx install-peerdeps --dev @leaflink/eslint-config
.- Optionally install
globals
if you have custom globals set in your projects eslint file: npm install -D globals
. - Rename
.eslintrc.js
to eslint.config.mjs
. - Refactor file to use esm syntax & ESLint flat configs. More below on this.
- Delete .eslintignore and move listed files/directories into an { ignores: [...] } block inside your ESLint config.
- Find/replace
@ts-ignore
-> @ts-expect-error
. Be aware, this may actually cause ts errors in the event that the @ts-ignore
wasn't actually doing anything. This is a good thing, just remove the comment altogether. - Change npm
lint
command: eslint --ext .ts,.js,.vue src
-> eslint .
. - Rename
stylelint.config.js
to stylelint.config.mjs
and refactor to esm. If using a json format, it should be fine to leave it as is. - Rename
commitlint.config.js
to stylelint.config.mjs
and refactor to esm. If using a json format, it should be fine to leave it as is.
You may also find yourself having to address certain eslint errors that didn't appear before. All 3rd party configs and plugins were upgraded as part of this update, hence some rules have been changed.
Docs: https://eslint.org/docs/latest/use/configure/migration-guide
Summary of main changes
- Your eslint file becomes an array of config objects instead of a single config object
- Global ignores need to be in their own object.
- Move all objects from
overrides
up a level - just "flatten" the overrides array and get rid of it. env
objects need to get converted to languageOptions: { globals: { ...globals.node, ...globals.jest } }
and you need to load globals from the globals
npm package. They aren't baked in anymore.files
always needs to be an array: files: '**/*.spec.ts'
-> files: ['**/*.spec.ts']
files
globs need to be a little more specific it seems. files: ['*.spec.ts']
-> files: ['**/*.spec.ts']
Example
Old usage (.eslintrc.js
):
module.exports = {
extends: 'leaflink',
};
New usage (eslint.config.mjs
):
import leaflinkConfig from '@leaflink/eslint-config';
export default [
...leaflinkConfig,
];
Usage
Create an eslint.config.mjs
file in the root of your project and extend from the shared LeafLink config.
[!IMPORTANT]
If you haven't enabled esm in your project by default, you may need to name your config file eslint.config.mjs
instead.
import leaflinkConfig from '@leaflink/eslint-config';
export default [
...leaflinkConfig,
{
rules: {
},
},
];
Prettier
Prettier is automatically run through eslint with LeafLink's default configuration. You can optionally add a prettier.config.js
configuration file in the root of your project and it will take precedence over the built-in config within @leaflink/eslint-config
.
If you'd like to extend our prettier config and only override a couple of properties, you can do the following:
prettier.config.mjs
import leaflinkConfig from '@leaflink/eslint-config/prettier.js';
const config = {
...leaflinkConfig,
};
export default config;
Stylelint
In your .stylelintrc
file, you can extend from the shared LeafLink stylelint config.
{
"extends": ["@leaflink/eslint-config/stylelint"]
}
Or you can do so in your package.json
:
{
"stylelint": {
"extends": ["@leaflink/eslint-config/stylelint"]
}
}
Or in stylelint.config.mjs
:
export default {
extends: ['@leaflink/eslint-config/stylelint'],
};
commitlint
Create a commitlint.config.mjs
in your project so you can extend from the shared LeafLink commitlint config.
import leaflinkConfig from '@leaflink/eslint-config/commitlint.js';
export default Object.assign(leaflinkConfig, {
rules: {
'scope-case': [1],
},
});
Tailwind class whitelist
There's a tailwindcss/no-custom-classname
rule that enforces the use of only valid global classes like Tailwind CSS utilities. You can allowlist custom global classes that you want to allow. Our config has a default allowlist of classes that are commonly used across our projects. If you need to add more classes to the allowlist, you can do so in your project's ESLint config file, but just be sure to include the default allowlist as well.
import leaflinkConfig, { TAILWIND_CLASS_ALLOWLIST } from '@leaflink/eslint-config';
export default [
...leaflinkConfig,
{
rules: {
'tailwindcss/no-custom-classname': [
'error',
{
whitelist: [
...TAILWIND_CLASS_ALLOWLIST,
'info-cell',
'table',
'col-2',
'col-10',
'col-1',
'col-3',
],
},
],
},
},
];
Known issues
https://github.com/francoismassart/eslint-plugin-tailwindcss/issues/149
When building dynamic classes, the auto sorting of tailwind classes can break things so beware:

To avoid this happening you can re-wrap the dynamic class expression like so:
class="`p-0 ${`tw-border-${accentColor}`}`"
Migrating LeafLink projects
- Uninstall your projects linting depedencies.
npm uninstall \
eslint-config-leaflink \
eslint \
@vue/eslint-config-prettier \
@vue/eslint-config-typescript \
eslint-plugin-simple-import-sort \
eslint-plugin-vue vue-eslint-parser \
eslint-plugin-testing-library \
@typescript-eslint/eslint-plugin \
@typescript-eslint/parser \
eslint-plugin-cypress \
stylelint \
stylelint-config-prettier \
stylelint-config-standard \
stylelint-config-standard-scss \
stylelint-config-standard-vue \
stylelint-order \
postcss-html \
@commitlint/cli \
@commitlint/config-conventional
- Optionally delete your project's stylelint config.
rm .stylelint.config.js .stylelintrc
- Optionally delete your project's prettier config and uninstall prettier unless it's used for non-js/yml things like markdown, etc.
npm uninstall prettier
rm .prettierrc.cjs .prettierrc.js .prettierrc
- Install
eslint-config-leaflink
.
npx install-peerdeps --dev @leaflink/eslint-config
- Optionally delete your projects
.eslintignore
file if our default list of ignores
is adequate. (Note: If you think there's a good general addition to this list, please open a PR). - Check to see if your eslintignore can be deleted. The shared config will only support high level ignore patterns.
ignorePatterns: ['dist', '!.github'],
- Update your projects' ESLint config.
module.exports = {
- extends: [
- 'plugin:vue/vue3-recommended',
- 'eslint:recommended',
- '@vue/eslint-config-typescript',
- '@vue/eslint-config-prettier',
- 'prettier',
- '@vue/prettier',
- '@vue/typescript',
- 'plugin:testing-library/vue',
- ],
- env: {
- es2021: true,
- browser: true,
- es6: true,
- node: true,
- jest: true,
- },
- plugins: [
- '@typescript-eslint',
- 'prettier',
- 'simple-import-sort',
- ],
- parser: 'vue-eslint-parser',
- parserOptions: {
- ecmaVersion: 2018,
- sourceType: 'module',
- parser: '@typescript-eslint/parser',
- },
+ extends: ['leaflink'],
+ // overrides...
}
- Update your projects'
package.json
.
- "commitlint": {
- "extends": [
- "@commitlint/config-conventional"
- ],
- "rules": {
- "scope-case": [
- 0
- ],
- "body-max-line-length": [
- 0
- ]
- }
- }
+ "stylelint": {
+ "extends": ["eslint-config-leaflink/stylelint"]
+ }
- Add a separate
commitlint.config.js
file.
const config = require('eslint-config-leaflink/commitlint');
module.exports = config;
Note: It's recommended you attempt to remove as many of your specific overrides as possible and see how much can be autofixed to be inline with this shared configuration. You can extend from leaflink
and set temporary overrides to turn some rules off in order to make the initial migration easier.