# Setup with Turborepo

Execute the following steps to set up ESLint for a monorepo solution managed with Turborepo 👇

# Setup the workspace

# Install the packages

Open a terminal at the root of the solution's workspace (the root of the repository) and install the following packages:

pnpm add -D @workleap/eslint-configs @eslint/js @typescript-eslint/parser @types/node eslint typescript-eslint turbo

# Configure Turborepo

First, create a configuration file named turbo.json at the root of the solution's workspace:

workspace
β”œβ”€β”€ packages
β”œβ”€β”€β”€β”€ pkg-1
β”œβ”€β”€β”€β”€β”€β”€ src
β”œβ”€β”€β”€β”€β”€β”€β”€β”€ ...
β”œβ”€β”€β”€β”€β”€β”€ package.json
β”œβ”€β”€ package.json
β”œβ”€β”€ turbo.json
β”œβ”€β”€ eslint.config.ts

Then, open the newly created file and copy/paste the following content:

turbo.json
{
    "$schema": "https://turbo.build/schema.json",
    "ui": "tui",
    "tasks": {
        "lint": {
            "dependsOn": ["eslint"]
        },
        "//#eslint": {
            "outputs": ["node_modules/.cache/eslint"]
        },
        "eslint": {
            "outputs": ["node_modules/.cache/eslint"]
        }
    }
}

The //#eslint task will execute the eslint script at the root of the solution's workspace and the eslint task will execute the eslint script for every project of the solution's workspace.

# Configure ESLint

Next, let's configure ESLint. Create a configuration file named eslint.config.ts at the root of the solution's workspace:

workspace
β”œβ”€β”€ packages
β”œβ”€β”€β”€β”€ pkg-1
β”œβ”€β”€β”€β”€β”€β”€ src
β”œβ”€β”€β”€β”€β”€β”€β”€β”€ ...
β”œβ”€β”€β”€β”€β”€β”€ package.json
β”œβ”€β”€ package.json
β”œβ”€β”€ turbo.json
β”œβ”€β”€ eslint.config.ts

Then, open the newly created file and extend the default configuration with the monorepo workspace shared configurations:

eslint.config.ts
import { defineMonorepoWorkspaceConfig } from "@workleap/eslint-configs";

export default defineMonorepoWorkspaceConfig(import.meta.dirname);

# Ignore files and folders

ESLint can be configured to ignore certain files and folders by specifying one or more glob patterns.

To do so, extend the eslint.config.ts file configuration at the root of the solution:

eslint.config.ts
import { defineMonorepoWorkspaceConfig } from "@workleap/eslint-configs";
import { defineConfig, globalIgnores } from "eslint/config";

export default defineConfig([
    globalIgnores([
        "packages",
        "samples",
        "docs"
    ]),
    defineMonorepoWorkspaceConfig(import.meta.dirname)
]);

# Configure indent style

@stylistic/eslint-plugin offers built-in rules for configuring the indentation style of a codebase. However, there's a catch: when VS Code auto-formatting feature is enabled, it might conflict with the configured indentation rules if they are set differently.

To guarantee a consistent indentation, we recommend using EditorConfig on the consumer side. With EditorConfig, the indent style can be configured in a single file and be applied consistently across various formatting tools, including ESlint and VS Code.

First, create a .editorconfig file at the root of the solution's workspace:

workspace
β”œβ”€β”€ packages
β”œβ”€β”€β”€β”€ pkg-1
β”œβ”€β”€β”€β”€β”€β”€ src
β”œβ”€β”€β”€β”€β”€β”€β”€β”€ ...
β”œβ”€β”€β”€β”€β”€β”€ package.json
β”œβ”€β”€ package.json
β”œβ”€β”€ turbo.json
β”œβ”€β”€ eslint.config.ts
β”œβ”€β”€ .editorconfig

Then, open the newly created file and paste the following configuration:

.editorconfig
root = true

[*]
charset = utf-8
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true
indent_style = space
indent_size = 4

[*.md]
trim_trailing_whitespace = false

# Add CLI scripts

Finally, add the lint and eslint scripts to your solution's workspace package.json file.

workspace
β”œβ”€β”€ packages
β”œβ”€β”€β”€β”€ pkg-1
β”œβ”€β”€β”€β”€β”€β”€ src
β”œβ”€β”€β”€β”€β”€β”€β”€β”€ ...
β”œβ”€β”€β”€β”€β”€β”€ package.json
β”œβ”€β”€ package.json    <------- (this one!)
β”œβ”€β”€ turbo.json
β”œβ”€β”€ eslint.config.ts
β”œβ”€β”€ .editorconfig

The lint script will execute the lint task and it's dependencies configured earlier in the turbo.json file:

package.json
{
    "lint": "turbo run lint --continue"
}

The eslint script will lint the root of the solution's workspace:

package.json
{
    "eslint": "eslint . --max-warnings=0 --cache --cache-location node_modules/.cache/eslint"
}

# Setup a project

# Install the packages

Open a terminal at the root of the project (packages/pkg-1 for this example) and install the following packages:

pnpm add -D @workleap/eslint-configs @eslint/js @typescript-eslint/parser @types/node eslint typescript-eslint

# Configure ESLint

First, create a configuration file named eslint.config.ts at the root of the project:

workspace
β”œβ”€β”€ packages
β”œβ”€β”€β”€β”€ pkg-1
β”œβ”€β”€β”€β”€β”€β”€ src
β”œβ”€β”€β”€β”€β”€β”€β”€β”€ ...
β”œβ”€β”€β”€β”€β”€β”€ package.json
β”œβ”€β”€β”€β”€β”€β”€ eslint.config.ts
β”œβ”€β”€ package.json
β”œβ”€β”€ eslint.config.ts
β”œβ”€β”€ .editorconfig

Then, open the newly created file and extend the default configuration with one of the shared configurations provided by @workleap/eslint-plugin 👇

# Web application

For an application developed with TypeScript and React, use the following configuration:

eslint.config.ts
import { defineWebApplicationConfig } from "@workleap/eslint-configs";

export default defineWebApplicationConfig(import.meta.dirname);

# React library

For a TypeScript library developed with React, use the following configuration:

eslint.config.ts
import { defineReactLibraryConfig } from "@workleap/eslint-configs";

export default defineReactLibraryConfig(import.meta.dirname);
# React compiler

If your application is set up with the React compiler, enable the React Compiler rules:

eslint.config.ts
import { defineReactLibraryConfig } from "@workleap/eslint-configs";

export default defineReactLibraryConfig(import.meta.dirname, {
    react: {
        compiler: true
    }
});

# TypeScript library

For a TypeScript library developed without React, use the following configuration:

eslint.config.ts
import { defineTypeScriptLibraryConfig } from "@workleap/eslint-configs";

export default defineTypeScriptLibraryConfig(import.meta.dirname);

# Add a CLI script

Finally, add the following eslint script to your project package.json file. This script will be executed by Turborepo:

packages/pkg-1/package.json
{
    "eslint": "eslint . --max-warnings=0 --cache --cache-location node_modules/.cache/eslint"
}

# Custom configuration

New projects shouldn't have to customize the default configurations offered by @workleap/eslint-configs. However, if you are in the process of migrating an existing project to use this library or encountering a challenging situation, refer to the custom configuration page to understand how to override or extend the default configurations. Remember, no locked in ❤️✌️.

# Try it 🚀

To test your new ESLint setup, open a JavaScript file, type invalid code (e.g. var x = 0;), then save. Open a terminal at the root of the solution and execute the CLI script added earlier:

pnpm lint

The terminal should output a linting error.

# Troubleshoot issues

Refer to the troubleshooting page.