Complete rewrite of linting setup#62
Conversation
📝 WalkthroughWalkthroughReplaces legacy CommonJS ESLint/Stylelint presets with a TypeScript flat-config system, adds an installer and CLI validators, reorganizes Prettier, updates CI/workflows and package metadata/exports, introduces workspace test packages, updates Node/TS targets, and removes many legacy wrapper modules and the publish workflow. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Dev as Developer
participant Installer as install.sh
participant FS as File System
participant NPM as Package Manager
participant ESLintBuilder as createVerkstedtConfig
participant Prettier as Prettier module
Dev->>Installer: run verkstedt-lint-setup <target-dir>
Installer->>FS: probe project files (package.json, tsconfig.json, .prettierignore)
Installer->>Installer: detect features (TypeScript, React, Next, CSS modules)
Installer->>NPM: install devDependencies (including local `@verkstedt/lint`)
Installer->>FS: create or update Prettier config and .prettierignore
Installer->>FS: write ESLint config referencing createVerkstedtConfig
Installer->>ESLintBuilder: invoke createVerkstedtConfig(dir, allowDefaultProject?)
ESLintBuilder->>FS: read package.json, .gitignore, tsconfig
ESLintBuilder->>ESLintBuilder: compose flat-config modules and resolve plugins
ESLintBuilder-->>Installer: return assembled config array (or error with missing deps)
Installer->>Prettier: validate or re-export Prettier config
Installer-->>Dev: exit with success or error
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Comment |
b6fd720 to
345e8ef
Compare
345e8ef to
e425f5d
Compare
48fe096 to
1ba8177
Compare
3c9c713 to
d649197
Compare
6e5d2d6 to
944f119
Compare
944f119 to
49b85b2
Compare
Currently only showed as a debug information. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Switch from eslint-config-next to @next/eslint-plugin-next. The config package bundled React, React Hooks, import, jsx-a11y, parser, and TypeScript config pieces that overlap with our own setup or block later ESLint 10 migration work. Keep the React rules that eslint-config-next previously contributed and that are still useful for JSX runtime projects, including JSX variable usage and selected Next-compatible React rule overrides. eslint-plugin-jsx-a11y@6.10.2 still caps its `eslint` peer at `^9` and no maintained fork supports ESLint 10 either. Drop the plugin entirely until upstream PR jsx-eslint/eslint-plugin-jsx-a11y#1081 ships. Documents the gap in README "Known caveats". Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-Authored-By: codex gpt-5.5 <codex@openai.com>
eslint-plugin-import does not support ESLint 10 yet. eslint-plugin-import-x is a maintained fork that already declares ESLint 10 in peerDependencies. Drop eslint-import-resolver-exports because its eslint-plugin-import peer pulls the incompatible package back in, and the exports resolver setting is not supported by eslint-plugin-import-x. Adds eslint-plugin-n purely for its prefer-node-protocol rule, which replaces the dropped import/enforce-node-protocol-usage rule that eslint-plugin-import-x doesn't ship. eslint-plugin-n was preferred over eslint-plugin-unicorn here because its 29 rules are all narrowly Node.js-focused and don't overlap with anything we already configure. Only n/prefer-node-protocol is enabled; the rest of the plugin is dormant. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-Authored-By: codex gpt-5.5 <codex@openai.com>
eslint-plugin-css-modules (last released 2023) calls context.getFilename(), which was removed in ESLint 10. @bhollis/eslint-plugin-css-modules is a maintained fork (released 2026-04-04) that ships flat configs and works with ESLint 10. Rule names are unchanged (`css-modules/no-unused-class`, `css-modules/no-undef-class`), so existing disable directives keep working. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-Authored-By: codex gpt-5.5 <codex@openai.com>
@eslint-react/eslint-plugin requires ESLint ^10.2.1, while eslint-plugin-react 7.37.5 only peers through ESLint 9.7. Move the React plugin migration and ESLint 10 upgrade together so npm install has no invalid peer intermediate state. Switch React rules to the @eslint-react namespace, keep eslint-plugin-react-hooks as the hook rules source, and update test fixtures to ESLint 10. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-Authored-By: codex gpt-5.5 <codex@openai.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
typescript-eslint caps its `typescript` peer at `<6.1.0`. Mirror that range in both peerDependencies and devDependencies so `npm install` resolves cleanly without npm coercing our spec on every install. Teaches `lint:pkg` to accept bounded peer specs (`^X <Y`) in addition to the existing `>=X` form, so the new TS pin doesn't trip the linter. Documented in a new "Known caveats" README section. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
allowJs can be undefined
|
Published new rc: https://npmx.dev/package/@verkstedt/lint/v/11.0.0-rc.8 (tagged |
It’s `yarn remove`, not `yarn uninstall`.
Note
eslint/index.tsandeslint/custom.ts.Why?
Closes https://verkstedt.atlassian.net/browse/VIP-19
Discussion
Caution
Do not discuss any internal verkstedt projects here. Discuss here: https://verkstedt.slack.com/archives/C8U48QUBA/p1767627900680289
Rollout
@verkstedt/lint@11.0.0-rc.1on npm@verkstedt/lint@11.0.0on npmlint@verkstedt/eslint-config-verkstedtas deprecated on npm and suggest migrating to@verkstedt/lintKnown issues
Collect first, then decide if any of these need to be addressed before the 11.0.0 release.
tsconfigit contains commentsextendsin tsconfig. A project might already extend something else, e.g.@tsconfig/vite-react. In that case, copy values fromtypescript/tsconfig.base.jsoninto yourtsconfig.css/use-baseline, but we should detect if features not defined in browserslist are used. There’sstylelint-no-unsupported-browser-features(not ideal, but it’s there), but I don’t think there’s anything like that for EsLint yet.Delayed to future versions
eslint-mdxWhat’s included?
Give README a read.
Prettier
Mostly defaults. Few overwrites where I tried to explain why.
StyleLint
Initially I thought I’d include style lint config as well, but nowadays eslint can do CSS as well, so maybe we don’t need it.
EsLint
Ignored files
.gitignorefrom the root of the repo.prettierignore— if your project has.eslintignorefile, please remove it and use only.prettierignore, so we can maintain only one of thoseConfigs
recommendedrecommendedfrom @eslint/jsonrecommendedfrom @eslint/markdownrecommendedfrom @eslint/cssNote: Switched away from
eslint-plugin-importtoeslint-plugin-import-xbecause it seems more actively maintained.recommendedtypescriptand eslint-import-resolver-typescript resolver.reactrecommendedstrict-type-checked(includesrecommended)stylistic-type-checkedNote: Switched away from
eslint-plugin-reactto@eslint-react/eslint-pluginbecause it seems more actively maintained.recommendedrecommended-type-checkedrecommendedNote: Not using whole config, because it includes import and react plugins, which we configure ourselves.
core-web-vitalsrecommendedrecommendedrecommendedrecommendedPurely for enforcing
node:for built–in module imports which is part ofeslint-plugin-import, but is absent fromeslint-plugin-import-x. We might enable more in the future.Custom config
Additional rules in https://github.com/verkstedt/eslint-config-verkstedt/blob/feat/rewrite/eslint/custom.ts
Testing
Assuming you have this repo cloned at e.g.
~/src/eslint-config-verkstedt, you can test it out in a different project using:npm install --save-dev ~/src/eslint-config-verkstedt@coderabbitai ignore