Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 0 additions & 64 deletions .github/DISCUSSION_TEMPLATE/eslint-suggestion.yml

This file was deleted.

55 changes: 55 additions & 0 deletions .github/DISCUSSION_TEMPLATE/oxlint-suggestion.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
body:
- type: markdown
attributes:
value: |-
Thank you for helping to improve `@epic-web/config`!

Please fill out the details below.

Keep in mind you can always extend the built-in configuration with your own config.
- type: textarea
attributes:
label: Search Terms Used
description: >-
Please list the search terms you used to search the discussions, issues,
and PRs before submitting this issue.
validations:
required: true
- type: input
attributes:
label: Rule or Config Docs
description: >-
Link to the Oxlint rule or configuration docs you're suggesting
changing
placeholder: https://oxc.rs/docs/guide/usage/linter/rules/
validations:
required: true
- type: textarea
attributes:
label: Suggested Change
description: >-
Write out the suggested change in configuration. If the rule or config is
already present, explain why it should be removed or changed. If it's not
present, explain why it should be added. And provide the final
configuration for the option.
validations:
required: true
- type: textarea
attributes:
label: Issues without the change
description: >-
Convince me why life is better with this change.
validations:
required: true
- type: textarea
attributes:
label: Severity of inaction
description: Convince me why not doing anything is bad.
validations:
required: true
- type: textarea
attributes:
label: Additional Context
description: Any other context that could be helpful.
validations:
required: false
7 changes: 4 additions & 3 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ contact_links:
about:
If you can't get something to work the way you expect, open a question in
the discussions.
- name: 👮 ESLint Rule Suggestion
url: https://github.com/epicweb-dev/config/discussions/new?category=eslint-suggestion
- name: 🐂 Oxlint Rule Suggestion
url: https://github.com/epicweb-dev/config/discussions/new?category=oxlint-suggestion
about:
We appreciate you taking the time to improve `@epic-web/config` with your
ideas, but we use the Discussions for this instead of the issues tab 🙂.
ideas, but we use Discussions for config suggestions instead of the issues
tab.
- name: 💬 Epic Web Discord Server
url: https://kcd.im/discord
about: Interact with other Epic Web developers
Expand Down
52 changes: 17 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<div>
<h1 align="center"><a href="https://npm.im/@epic-web/config">👮 @epic-web/config</a></h1>
<strong>
Reasonable ESLint, Oxlint, Prettier, and TypeScript configs for epic web devs
Reasonable Oxlint, Prettier, and TypeScript configs for epic web devs
</strong>
<p>
This makes assumptions about the way you prefer to develop software and gives you configurations that will actually help you in your development.
Expand Down Expand Up @@ -40,8 +40,11 @@ configuring code quality tools or babysitting them.

## This solution

This is a set of configurations you can use in your web projects to avoid
wasting time.
This package provides shared defaults for the tools this repo currently ships:

- Oxlint
- Prettier
- TypeScript

## Decisions

Expand Down Expand Up @@ -114,33 +117,6 @@ Learn more from

</details>

### ESLint

Create a `eslint.config.js` file in your project root with the following
content:

```js
import { config as defaultConfig } from '@epic-web/config/eslint'

/** @type {import("eslint").Linter.Config[]} */
export default [...defaultConfig]
```

<details>
<summary>Customizing ESLint</summary>

Learn more from
[the Eslint docs here](https://eslint.org/docs/latest/extend/shareable-configs#overriding-settings-from-shareable-configs).

</details>

There are endless rules we could enable. However, we want to keep our
configurations minimal and only enable rules that catch real problems (the kind
that are likely to happen). This keeps our linting faster and reduces the number
of false positives.

Custom rule documentation lives in [`lint-rules/index.md`](./lint-rules/index.md).

### Oxlint

Create a `.oxlintrc.json` file in your project root with the following content:
Expand All @@ -151,22 +127,28 @@ Create a `.oxlintrc.json` file in your project root with the following content:
}
```

This config includes the custom `epic-web/*` rules documented in
[`lint-rules/index.md`](./lint-rules/index.md).

Note: `typescript/no-misused-promises` and `typescript/no-floating-promises` are
type-aware in Oxlint and require the type-aware setup described in the Oxlint
docs.

#### Unsupported rules
Some Oxlint rule IDs still use the `eslint/` namespace because that is how
Oxlint exposes those compatibility rules. You do not need to install ESLint to
use them.

#### Not yet covered

The following ESLint rules/plugins from this config are not yet available in
Oxlint, so they are intentionally omitted:
The following rule families are intentionally omitted because they are not yet
part of the Oxlint config this package ships:

- `import/order`
- `react-hooks/rules-of-hooks`
- `react-hooks/exhaustive-deps`
- `@typescript-eslint/no-unused-vars` (falls back to `eslint/no-unused-vars`)
- `testing-library/*`
- `jest-dom/*`
- `vitest/*` (except `vitest/no-import-node-test`)
- most `vitest/*` rules
- `playwright/*`

## License
Expand Down
41 changes: 41 additions & 0 deletions docs/decisions/010-move-to-oxlint.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Move to Oxlint

Date: 2026-03-26

Status: accepted

## Context

This package originally shipped both ESLint and Oxlint configuration. Over time,
the Oxlint side of the package became the simpler path to maintain and consume.

There are a few reasons for that:

1. Oxlint is dramatically faster, which makes local feedback and CI validation
cheaper.
2. The configuration story is simpler when we only ship one linting toolchain.
3. The Oxlint project has an active and clearly invested team behind it, which
makes it a good foundation to build on.
4. Oxlint's compatibility with many established ESLint rule IDs makes migration
straightforward, so moving away from ESLint does not require a wholesale
rethink of the existing rule set.

Because Oxlint can consume many familiar `eslint/...` rule identifiers and we
already author our custom rules as Oxlint JS plugins, the migration path is
mostly about removing duplicate package surface rather than redesigning the
linting rules themselves.

## Decision

Ship Oxlint as the package's linting solution and remove the published ESLint
configs, ESLint plugin entry points, and ESLint package dependencies.

## Consequences

- Consumers must migrate from the removed ESLint entry points to the Oxlint
config.
- Some rule IDs may continue to use the `eslint/` namespace inside Oxlint
config, because that is how Oxlint exposes compatibility rules.
- The package becomes smaller and easier to maintain because it only supports a
single linting toolchain.
- Linting should be faster for both maintainers and consumers.
9 changes: 4 additions & 5 deletions docs/style-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -1073,10 +1073,9 @@ function calculateTotal(items: Array<number>) {

Don't use semicolons. The rules for when you should use semicolons are more
complicated than the rules for when you must use semicolons. With the right
eslint rule
([`no-unexpected-multiline`](https://eslint.org/docs/latest/rules/no-unexpected-multiline))
and a formatter that will format your code funny for you if you mess up, you can
avoid the pitfalls. Read more about this in
Oxlint rule (`eslint/no-unexpected-multiline`) and a formatter that will format
your code funny for you if you mess up, you can avoid the pitfalls. Read more
about this in
[Semicolons in JavaScript: A preference](https://kentcdodds.com/blog/semicolons-in-javascript-a-preference).

<!-- prettier-ignore -->
Expand Down Expand Up @@ -1826,7 +1825,7 @@ test('Form shows error for invalid email', async () => {

Prioritize your tests according to the Testing Trophy:

1. Static Analysis (TypeScript, ESLint)
1. Static Analysis (TypeScript, Oxlint)
2. Unit Tests (Pure Functions)
3. Integration Tests (Component Integration)
4. E2E Tests (Critical User Flows)
Expand Down
3 changes: 0 additions & 3 deletions eslint-plugin-epic-web.js

This file was deleted.

1 change: 0 additions & 1 deletion eslint.config.js

This file was deleted.

Loading