|
| 1 | +# ESLint in Plane - How It Works |
| 2 | + |
| 3 | +We've recently upgraded our ESLint setup to use **typed linting** with a **single root-level configuration**. This means faster lint runs and simpler config management across the entire monorepo. |
| 4 | + |
| 5 | +## Key Changes |
| 6 | + |
| 7 | +1. **Single Root Config** - Instead of individual `eslint.config.mjs` files in every package, we now have one config at the repo root that handles all packages and apps |
| 8 | +2. **Typed Linting Enabled** - ESLint now uses TypeScript's type information for more powerful checks (catching things like floating promises, unsafe any usage, etc.) |
| 9 | +3. **ESLint Flat Config** - We're using ESLint v9's new flat config format |
| 10 | + |
| 11 | +## How to Run ESLint |
| 12 | + |
| 13 | +From the root of the repo: |
| 14 | + |
| 15 | +```bash |
| 16 | +# Check for lint errors |
| 17 | +pnpm check:lint |
| 18 | + |
| 19 | +# Auto-fix lint errors |
| 20 | +pnpm fix:lint |
| 21 | +``` |
| 22 | + |
| 23 | +## VS Code Integration |
| 24 | + |
| 25 | +ESLint should work automatically in VS Code. The extension will: |
| 26 | + |
| 27 | +- Show inline errors/warnings as you type |
| 28 | +- Use the root `eslint.config.mjs` for all files in the monorepo |
| 29 | + |
| 30 | +**Tip:** Make sure you have the [ESLint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) installed. |
| 31 | + |
| 32 | +## What Gets Linted |
| 33 | + |
| 34 | +The config applies to all TypeScript and JavaScript files across: |
| 35 | + |
| 36 | +- `apps/web`, `apps/admin`, `apps/space`, `apps/live` |
| 37 | +- All packages in `packages/` |
| 38 | + |
| 39 | +**Ignored paths:** |
| 40 | + |
| 41 | +- `node_modules/`, `dist/`, `build/`, `.next/`, `.turbo/` |
| 42 | +- Config files (`*.config.{js,mjs,cjs,ts}`) |
| 43 | +- Public folders |
| 44 | + |
| 45 | +## Rules Overview |
| 46 | + |
| 47 | +We're enforcing warnings (not errors) for most rules during the transition period. Key categories: |
| 48 | + |
| 49 | +| Category | What It Catches | |
| 50 | +| ----------------- | -------------------------------------------------------------------------------- | |
| 51 | +| **TypeScript** | `no-explicit-any`, `no-floating-promises`, `no-unsafe-*` family, unused vars | |
| 52 | +| **React** | Display names, hooks rules (including new React Compiler rules), refresh exports | |
| 53 | +| **Accessibility** | Alt text, keyboard events, ARIA roles, focus management | |
| 54 | +| **Imports** | Type imports style (`prefer-top-level`), unresolved imports | |
| 55 | +| **Promises** | Always return, catch-or-return | |
| 56 | + |
| 57 | +## Adding New Packages |
| 58 | + |
| 59 | +When creating a new package, **you don't need to add an ESLint config**. Just ensure: |
| 60 | + |
| 61 | +1. The package has a `tsconfig.json` |
| 62 | +2. The `tsconfig.json` is discoverable via the pattern `{apps,packages}/*/tsconfig.json` |
| 63 | + |
| 64 | +The root config will automatically pick it up. |
| 65 | + |
| 66 | +## Suppressing Warnings |
| 67 | + |
| 68 | +If you need to suppress a specific warning: |
| 69 | + |
| 70 | +```typescript |
| 71 | +// Single line |
| 72 | +// eslint-disable-next-line @typescript-eslint/no-explicit-any |
| 73 | +const data: any = response; |
| 74 | + |
| 75 | +// Block |
| 76 | +/* eslint-disable @typescript-eslint/no-unsafe-assignment */ |
| 77 | +// ... code |
| 78 | +/* eslint-enable @typescript-eslint/no-unsafe-assignment */ |
| 79 | +``` |
| 80 | + |
| 81 | +**Please use sparingly** - most warnings indicate real issues that should be fixed. |
| 82 | + |
| 83 | +## Pre-commit Hook |
| 84 | + |
| 85 | +Lint-staged runs automatically on commit via Husky: |
| 86 | + |
| 87 | +- Prettier formats your staged files |
| 88 | +- ESLint fixes what it can (with `--max-warnings=0`) |
| 89 | + |
| 90 | +If the commit fails due to lint errors, fix them before committing. |
| 91 | + |
| 92 | +## Reference Files |
| 93 | + |
| 94 | +- [eslint.config.mjs](../eslint.config.mjs) - Full ESLint configuration |
| 95 | +- [package.json](../package.json) - Available scripts |
| 96 | + |
| 97 | +## Help Us Improve! |
| 98 | + |
| 99 | +If you have the time, please consider trying to put up PRs to turn the rules I've set to `warn` to `error`, or getting all of strict mode in TypeScript working for a package (e.g., `noUncheckedIndexAccess`, `strictNullChecks`). It'll help prevent bugs at Plane, and your co-workers will unknowingly thank you for it. |
| 100 | + |
| 101 | +If you do decide to tackle this, please feel free to reach out to [@lifeiscontent](https://github.com/lifeiscontent) for advice on issues you get stuck on. |
| 102 | + |
| 103 | +Thanks! |
0 commit comments