react-doctor 0.0.47 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +124 -233
- package/dist/cli.js +941 -226
- package/dist/eslint-plugin.d.ts +57 -0
- package/dist/eslint-plugin.js +6965 -0
- package/dist/index.d.ts +33 -2
- package/dist/index.js +908 -398
- package/dist/react-doctor-plugin.js +2010 -320
- package/package.json +9 -13
- package/dist/browser-BOxs7MrK.js +0 -359
- package/dist/browser-Dcq3yn-p.d.ts +0 -146
- package/dist/browser.d.ts +0 -2
- package/dist/browser.js +0 -2
- package/dist/worker.d.ts +0 -2
- package/dist/worker.js +0 -2
package/README.md
CHANGED
|
@@ -7,22 +7,13 @@
|
|
|
7
7
|
[](https://npmjs.com/package/react-doctor)
|
|
8
8
|
[](https://npmjs.com/package/react-doctor)
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Your agent writes bad React, this catches it.
|
|
11
11
|
|
|
12
|
-
One command scans your codebase
|
|
12
|
+
One command scans your codebase and outputs a **0 to 100 health score** with actionable diagnostics.
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
https://github.com/user-attachments/assets/07cc88d9-9589-44c3-aa73-5d603cb1c570
|
|
17
|
-
|
|
18
|
-
## How it works
|
|
19
|
-
|
|
20
|
-
React Doctor detects your framework (Next.js, Vite, Remix, etc.), React version, and compiler setup, then runs two analysis passes **in parallel**:
|
|
14
|
+
Works with Next.js, Vite, and React Native.
|
|
21
15
|
|
|
22
|
-
|
|
23
|
-
2. **Dead code**: Detects unused files, exports, types, and duplicates.
|
|
24
|
-
|
|
25
|
-
Diagnostics are filtered through your config, then scored by severity (errors weigh more than warnings) to produce a **0–100 health score** (75+ Great, 50–74 Needs work, <50 Critical).
|
|
16
|
+
### [See it in action →](https://react.doctor)
|
|
26
17
|
|
|
27
18
|
## Install
|
|
28
19
|
|
|
@@ -32,23 +23,21 @@ Run this at your project root:
|
|
|
32
23
|
npx -y react-doctor@latest .
|
|
33
24
|
```
|
|
34
25
|
|
|
35
|
-
|
|
26
|
+
You'll get a score (75+ Great, 50 to 74 Needs work, under 50 Critical) and a list of issues across state & effects, performance, architecture, security, accessibility, and dead code. Rules toggle automatically based on your framework and React version.
|
|
36
27
|
|
|
37
|
-
|
|
38
|
-
npx -y react-doctor@latest . --verbose
|
|
39
|
-
```
|
|
28
|
+
https://github.com/user-attachments/assets/07cc88d9-9589-44c3-aa73-5d603cb1c570
|
|
40
29
|
|
|
41
30
|
## Install for your coding agent
|
|
42
31
|
|
|
43
|
-
Teach your coding agent React best practices
|
|
32
|
+
Teach your coding agent React best practices so it stops writing the bad code in the first place.
|
|
44
33
|
|
|
45
34
|
```bash
|
|
46
35
|
npx -y react-doctor@latest install
|
|
47
36
|
```
|
|
48
37
|
|
|
49
|
-
You'll be prompted to pick which detected agents to install for. Pass `--yes` to skip prompts
|
|
38
|
+
You'll be prompted to pick which detected agents to install for. Pass `--yes` to skip prompts.
|
|
50
39
|
|
|
51
|
-
|
|
40
|
+
Works with Claude Code, Cursor, Codex, OpenCode, and 50+ other agents.
|
|
52
41
|
|
|
53
42
|
## GitHub Actions
|
|
54
43
|
|
|
@@ -62,289 +51,191 @@ Supports 50+ coding agents via [`agent-install`](https://www.npmjs.com/package/a
|
|
|
62
51
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
63
52
|
```
|
|
64
53
|
|
|
65
|
-
|
|
66
|
-
| -------------- | ------- | ----------------------------------------------------------------- |
|
|
67
|
-
| `directory` | `.` | Project directory to scan |
|
|
68
|
-
| `verbose` | `true` | Show file details per rule |
|
|
69
|
-
| `project` | | Workspace project(s) to scan (comma-separated) |
|
|
70
|
-
| `diff` | | Base branch for diff mode. Only changed files are scanned |
|
|
71
|
-
| `github-token` | | When set on `pull_request` events, posts findings as a PR comment |
|
|
72
|
-
| `fail-on` | `error` | Exit with error code on diagnostics: `error`, `warning`, `none` |
|
|
73
|
-
| `offline` | `false` | Skip sending diagnostics to the react.doctor API |
|
|
74
|
-
| `node-version` | `22` | Node.js version to use |
|
|
75
|
-
|
|
76
|
-
The action outputs a `score` (0–100) you can use in subsequent steps.
|
|
77
|
-
|
|
78
|
-
## Options
|
|
79
|
-
|
|
80
|
-
```
|
|
81
|
-
Usage: react-doctor [directory] [options]
|
|
82
|
-
|
|
83
|
-
Options:
|
|
84
|
-
-v, --version display the version number
|
|
85
|
-
--no-lint skip linting
|
|
86
|
-
--no-dead-code skip dead code detection
|
|
87
|
-
--verbose show file details per rule
|
|
88
|
-
--score output only the score
|
|
89
|
-
--json output a single structured JSON report (suppresses other output)
|
|
90
|
-
-y, --yes skip prompts, scan all workspace projects
|
|
91
|
-
--full skip prompts, always run a full scan (decline diff-only)
|
|
92
|
-
--project <name> select workspace project (comma-separated for multiple)
|
|
93
|
-
--diff [base] scan only files changed vs base branch
|
|
94
|
-
--offline skip telemetry (anonymous, not stored, only used to calculate score)
|
|
95
|
-
--staged scan only staged (git index) files for pre-commit hooks
|
|
96
|
-
--fail-on <level> exit with error code on diagnostics: error, warning, none
|
|
97
|
-
--annotations output diagnostics as GitHub Actions annotations
|
|
98
|
-
-h, --help display help for command
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
## JSON output
|
|
102
|
-
|
|
103
|
-
Pass `--json` to get a single, parsable JSON object on stdout. All human-readable output, prompts, and the share link are suppressed; pipe straight into `jq`, `node`, or any other tool:
|
|
104
|
-
|
|
105
|
-
```bash
|
|
106
|
-
npx -y react-doctor@latest . --json | jq '.summary'
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
Exit code is `0` on success and `1` if the scan throws or `--fail-on` is triggered. Errors still produce a JSON object with `ok: false`, so the stdout is always a valid document.
|
|
110
|
-
|
|
111
|
-
### Schema
|
|
112
|
-
|
|
113
|
-
```ts
|
|
114
|
-
interface JsonReport {
|
|
115
|
-
schemaVersion: 1;
|
|
116
|
-
version: string; // react-doctor version
|
|
117
|
-
ok: boolean; // false when an error was thrown
|
|
118
|
-
directory: string; // resolved root passed to the CLI
|
|
119
|
-
mode: "full" | "diff" | "staged";
|
|
120
|
-
diff: {
|
|
121
|
-
baseBranch: string;
|
|
122
|
-
currentBranch: string;
|
|
123
|
-
changedFileCount: number;
|
|
124
|
-
isCurrentChanges: boolean;
|
|
125
|
-
} | null;
|
|
126
|
-
projects: Array<{
|
|
127
|
-
directory: string;
|
|
128
|
-
project: ProjectInfo;
|
|
129
|
-
diagnostics: Diagnostic[];
|
|
130
|
-
score: { score: number; label: string } | null;
|
|
131
|
-
skippedChecks: string[];
|
|
132
|
-
elapsedMilliseconds: number;
|
|
133
|
-
}>;
|
|
134
|
-
diagnostics: Diagnostic[]; // flattened across all scanned projects
|
|
135
|
-
summary: {
|
|
136
|
-
errorCount: number;
|
|
137
|
-
warningCount: number;
|
|
138
|
-
affectedFileCount: number;
|
|
139
|
-
totalDiagnosticCount: number;
|
|
140
|
-
score: number | null; // worst project score, when available
|
|
141
|
-
scoreLabel: string | null;
|
|
142
|
-
};
|
|
143
|
-
elapsedMilliseconds: number; // total wall time across all projects
|
|
144
|
-
error: {
|
|
145
|
-
message: string;
|
|
146
|
-
name: string;
|
|
147
|
-
chain: string[]; // outer error message first, every `error.cause`
|
|
148
|
-
// unwrapped after; chain[0] always equals `message`
|
|
149
|
-
} | null; // null on success, populated when ok=false
|
|
150
|
-
}
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
## Browser API
|
|
154
|
-
|
|
155
|
-
Import `react-doctor/browser` to run the same **diagnostics merge, config-based filtering, timing, and scoring pipeline** as `react-doctor/api`’s `diagnose`, but with **caller-supplied** inputs: `project` metadata, a virtual `projectFiles` map (contents keyed by paths relative to `rootDirectory`) for ignore/suppression resolution, and a `runOxlint` callback that performs linting in your environment (for example a Web Worker with oxlint).
|
|
156
|
-
|
|
157
|
-
Git history, real filesystem discovery, knip, the CLI, staged-file detection, and interactive prompts are **not** available in the browser bundle; treat those as Node-only or supply equivalents yourself. `react-doctor/worker` re-exports the same browser-facing modules for worker targets.
|
|
158
|
-
|
|
159
|
-
If you call **`diagnoseCore`** yourself in the browser, pass **`calculateDiagnosticsScore`** from this package (re-exported as **`calculateScore`** on `react-doctor/browser`) so the bundle never pulls in Node-only proxy code.
|
|
54
|
+
When `github-token` is set on `pull_request` events, findings are posted as a PR comment. The action also outputs a `score` (0 to 100) you can use in subsequent steps.
|
|
160
55
|
|
|
161
56
|
## Configuration
|
|
162
57
|
|
|
163
|
-
Create a `react-doctor.config.json` in your project root
|
|
58
|
+
Create a `react-doctor.config.json` in your project root:
|
|
164
59
|
|
|
165
60
|
```json
|
|
166
61
|
{
|
|
167
62
|
"ignore": {
|
|
168
|
-
"rules": ["react/no-danger", "jsx-a11y/no-autofocus"
|
|
169
|
-
"files": ["src/generated/**"]
|
|
63
|
+
"rules": ["react/no-danger", "jsx-a11y/no-autofocus"],
|
|
64
|
+
"files": ["src/generated/**"],
|
|
65
|
+
"overrides": [
|
|
66
|
+
{
|
|
67
|
+
"files": ["components/diff/**"],
|
|
68
|
+
"rules": ["react-doctor/no-array-index-as-key"]
|
|
69
|
+
}
|
|
70
|
+
]
|
|
170
71
|
}
|
|
171
72
|
}
|
|
172
73
|
```
|
|
173
74
|
|
|
174
|
-
You can also use the `"reactDoctor"` key in
|
|
75
|
+
`ignore.rules` silences a rule everywhere. `ignore.files` silences every rule on matched files. `ignore.overrides` silences specific rules in specific directories. You can also use the `"reactDoctor"` key in `package.json`. CLI flags always override config values.
|
|
175
76
|
|
|
176
|
-
|
|
177
|
-
{
|
|
178
|
-
"reactDoctor": {
|
|
179
|
-
"ignore": {
|
|
180
|
-
"rules": ["react/no-danger"]
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
```
|
|
77
|
+
React Doctor respects `.gitignore`, `.eslintignore`, `.oxlintignore`, `.prettierignore`, and `linguist-vendored` / `linguist-generated` annotations in `.gitattributes`. Inline `// eslint-disable*` and `// oxlint-disable*` comments are honored too.
|
|
185
78
|
|
|
186
|
-
If
|
|
79
|
+
If you have a JSON oxlint or eslint config (`.oxlintrc.json` or `.eslintrc.json`), its rules get merged into the scan automatically and count toward the score. Set `adoptExistingLintConfig: false` to opt out.
|
|
187
80
|
|
|
188
81
|
### Inline suppressions
|
|
189
82
|
|
|
190
|
-
Suppress a rule on a specific line with `// react-doctor-disable-line` or the next line with `// react-doctor-disable-next-line`:
|
|
191
|
-
|
|
192
83
|
```tsx
|
|
193
84
|
// react-doctor-disable-next-line react-doctor/no-cascading-set-state
|
|
194
85
|
useEffect(() => {
|
|
195
86
|
setA(value);
|
|
196
87
|
setB(value);
|
|
197
|
-
setC(value);
|
|
198
88
|
}, [value]);
|
|
199
|
-
|
|
200
|
-
const value = expensiveComputation(); // react-doctor-disable-line react-doctor/no-usememo-simple-expression
|
|
201
89
|
```
|
|
202
90
|
|
|
203
|
-
|
|
91
|
+
When two rules fire on the same line, comma-separate the rule ids on a single comment. Block comments work inside JSX:
|
|
204
92
|
|
|
205
|
-
|
|
93
|
+
<!-- prettier-ignore -->
|
|
94
|
+
```tsx
|
|
95
|
+
{/* react-doctor-disable-next-line react/no-danger */}
|
|
96
|
+
<div dangerouslySetInnerHTML={{ __html }} />
|
|
97
|
+
```
|
|
206
98
|
|
|
207
|
-
|
|
99
|
+
For multi-line JSX, putting the comment immediately above the opening tag covers the entire attribute list (matching ESLint convention).
|
|
208
100
|
|
|
209
|
-
|
|
210
|
-
| ------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
211
|
-
| `.gitignore` | files git ignores (oxlint default) |
|
|
212
|
-
| `.eslintignore` | files eslint skips (oxlint default) |
|
|
213
|
-
| `.oxlintignore` | files oxlint skips (added via `--ignore-pattern` so `.eslintignore` still applies) |
|
|
214
|
-
| `.prettierignore` | files prettier skips — typically vendored code, generated builds, and lockfiles |
|
|
215
|
-
| `.gitattributes` (`linguist-vendored`, `linguist-generated`) | paths GitHub's linguist library hides from language stats; if it's not "your" code by GitHub's reckoning, it shouldn't be audited as your code by react-doctor either |
|
|
101
|
+
## Lint plugin (standalone)
|
|
216
102
|
|
|
217
|
-
|
|
103
|
+
The same rule set ships as both an oxlint plugin and an ESLint plugin, so you can wire it into whichever lint engine your project already runs.
|
|
218
104
|
|
|
219
|
-
|
|
220
|
-
- `// eslint-disable`, `// eslint-disable-line`, `// eslint-disable-next-line` — oxlint reads both prefixes interchangeably.
|
|
105
|
+
**oxlint** in `.oxlintrc.json`:
|
|
221
106
|
|
|
222
|
-
|
|
107
|
+
```jsonc
|
|
108
|
+
{
|
|
109
|
+
"jsPlugins": [{ "name": "react-doctor", "specifier": "react-doctor/oxlint-plugin" }],
|
|
110
|
+
"rules": {
|
|
111
|
+
"react-doctor/no-fetch-in-effect": "warn",
|
|
112
|
+
"react-doctor/no-derived-state-effect": "warn",
|
|
113
|
+
},
|
|
114
|
+
}
|
|
115
|
+
```
|
|
223
116
|
|
|
224
|
-
|
|
117
|
+
**ESLint** flat config:
|
|
225
118
|
|
|
226
|
-
```
|
|
227
|
-
|
|
119
|
+
```js
|
|
120
|
+
import reactDoctor from "react-doctor/eslint-plugin";
|
|
121
|
+
|
|
122
|
+
export default [
|
|
123
|
+
reactDoctor.configs.recommended,
|
|
124
|
+
reactDoctor.configs.next,
|
|
125
|
+
reactDoctor.configs["react-native"],
|
|
126
|
+
reactDoctor.configs["tanstack-start"],
|
|
127
|
+
reactDoctor.configs["tanstack-query"],
|
|
128
|
+
];
|
|
228
129
|
```
|
|
229
130
|
|
|
230
|
-
|
|
131
|
+
The full rule list lives in [`oxlint-config.ts`](https://github.com/millionco/react-doctor/blob/main/packages/react-doctor/src/oxlint-config.ts).
|
|
231
132
|
|
|
232
|
-
|
|
133
|
+
## CLI reference
|
|
233
134
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
| `ignore.rules` | `string[]` | `[]` | Rules to suppress, using the `plugin/rule` format shown in diagnostic output (e.g. `react/no-danger`, `knip/exports`, `knip/types`) |
|
|
237
|
-
| `ignore.files` | `string[]` | `[]` | File paths to exclude, supports glob patterns (`src/generated/**`, `**/*.test.tsx`) |
|
|
238
|
-
| `lint` | `boolean` | `true` | Enable/disable lint checks (same as `--no-lint`) |
|
|
239
|
-
| `deadCode` | `boolean` | `true` | Enable/disable dead code detection (same as `--no-dead-code`) |
|
|
240
|
-
| `verbose` | `boolean` | `false` | Show file details per rule (same as `--verbose`) |
|
|
241
|
-
| `diff` | `boolean \| string` | — | Force diff mode (`true`) or pin a base branch (`"main"`). Set to `false` to disable auto-detection. |
|
|
242
|
-
| `failOn` | `"error" \| "warning" \| "none"` | `"none"` | Exit with error code on diagnostics of the given severity or above |
|
|
243
|
-
| `customRulesOnly` | `boolean` | `false` | Disable built-in react/jsx-a11y/compiler rules, keeping only `react-doctor/*` plugin rules |
|
|
244
|
-
| `share` | `boolean` | `true` | Show the share-your-results URL after scanning |
|
|
245
|
-
| `textComponents` | `string[]` | `[]` | React Native only. Component names whose children should not trigger `rn-no-raw-text` (e.g. `["MyText", "Label.Bold"]`) |
|
|
246
|
-
| `respectInlineDisables` | `boolean` | `true` | Respect inline `// eslint-disable*` / `// oxlint-disable*` comments. Set `false` for audit mode. File-level ignores (`.gitignore`, `.eslintignore`, `.oxlintignore`, `.prettierignore`, `.gitattributes` linguist annotations) are always respected. |
|
|
135
|
+
```
|
|
136
|
+
Usage: react-doctor [directory] [options]
|
|
247
137
|
|
|
248
|
-
|
|
138
|
+
Options:
|
|
139
|
+
-v, --version display the version number
|
|
140
|
+
--no-lint skip linting
|
|
141
|
+
--no-dead-code skip dead code detection
|
|
142
|
+
--verbose show every rule and per-file details (default shows top 3 rules)
|
|
143
|
+
--score output only the score
|
|
144
|
+
--json output a single structured JSON report
|
|
145
|
+
-y, --yes skip prompts, scan all workspace projects
|
|
146
|
+
--full skip prompts, always run a full scan
|
|
147
|
+
--project <name> select workspace project (comma-separated for multiple)
|
|
148
|
+
--diff [base] scan only files changed vs base branch
|
|
149
|
+
--staged scan only staged files (for pre-commit hooks)
|
|
150
|
+
--offline skip telemetry
|
|
151
|
+
--fail-on <level> exit with error on diagnostics: error, warning, none
|
|
152
|
+
--annotations output diagnostics as GitHub Actions annotations
|
|
153
|
+
--explain <file:line> diagnose why a rule fired or why a suppression didn't apply
|
|
154
|
+
-h, --help display help
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
When a suppression isn't working, `--explain <file:line>` reports what the scanner sees at that location, including why a nearby `react-doctor-disable-next-line` didn't apply. The same hint surfaces inline with `--verbose` and in `--json` output as `diagnostic.suppressionHint`.
|
|
158
|
+
|
|
159
|
+
`--json` produces a parsable object on stdout with all human-readable output suppressed. Errors still produce a JSON object with `ok: false`, so stdout is always a valid document.
|
|
160
|
+
|
|
161
|
+
### Config keys
|
|
162
|
+
|
|
163
|
+
| Key | Type | Default |
|
|
164
|
+
| ------------------------- | -------------------------------- | -------- |
|
|
165
|
+
| `ignore.rules` | `string[]` | `[]` |
|
|
166
|
+
| `ignore.files` | `string[]` | `[]` |
|
|
167
|
+
| `ignore.overrides` | `{ files, rules? }[]` | `[]` |
|
|
168
|
+
| `lint` | `boolean` | `true` |
|
|
169
|
+
| `deadCode` | `boolean` | `true` |
|
|
170
|
+
| `verbose` | `boolean` | `false` |
|
|
171
|
+
| `diff` | `boolean \| string` | |
|
|
172
|
+
| `failOn` | `"error" \| "warning" \| "none"` | `"none"` |
|
|
173
|
+
| `customRulesOnly` | `boolean` | `false` |
|
|
174
|
+
| `share` | `boolean` | `true` |
|
|
175
|
+
| `textComponents` | `string[]` | `[]` |
|
|
176
|
+
| `respectInlineDisables` | `boolean` | `true` |
|
|
177
|
+
| `adoptExistingLintConfig` | `boolean` | `true` |
|
|
249
178
|
|
|
250
179
|
## Node.js API
|
|
251
180
|
|
|
252
|
-
You can also use React Doctor programmatically:
|
|
253
|
-
|
|
254
181
|
```js
|
|
255
|
-
import { diagnose } from "react-doctor/api";
|
|
182
|
+
import { diagnose, toJsonReport, summarizeDiagnostics } from "react-doctor/api";
|
|
256
183
|
|
|
257
184
|
const result = await diagnose("./path/to/your/react-project");
|
|
258
185
|
|
|
259
186
|
console.log(result.score); // { score: 82, label: "Great" } or null
|
|
260
|
-
console.log(result.diagnostics); //
|
|
261
|
-
console.log(result.project); //
|
|
187
|
+
console.log(result.diagnostics); // Diagnostic[]
|
|
188
|
+
console.log(result.project); // detected framework, React version, etc.
|
|
262
189
|
```
|
|
263
190
|
|
|
264
|
-
|
|
191
|
+
`diagnose` accepts a second argument: `{ lint?: boolean, deadCode?: boolean }`.
|
|
265
192
|
|
|
266
193
|
```js
|
|
267
|
-
const result = await diagnose(".", {
|
|
268
|
-
lint: true, // run lint checks (default: true)
|
|
269
|
-
deadCode: true, // run dead code detection (default: true)
|
|
270
|
-
});
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
Each diagnostic has the following shape:
|
|
274
|
-
|
|
275
|
-
```ts
|
|
276
|
-
interface Diagnostic {
|
|
277
|
-
filePath: string;
|
|
278
|
-
plugin: string;
|
|
279
|
-
rule: string;
|
|
280
|
-
severity: "error" | "warning";
|
|
281
|
-
message: string;
|
|
282
|
-
help: string;
|
|
283
|
-
line: number;
|
|
284
|
-
column: number;
|
|
285
|
-
category: string;
|
|
286
|
-
}
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
To produce the same structured output the `--json` CLI flag emits, use `toJsonReport`:
|
|
290
|
-
|
|
291
|
-
```js
|
|
292
|
-
import { diagnose, toJsonReport, summarizeDiagnostics } from "react-doctor/api";
|
|
293
|
-
|
|
294
|
-
const result = await diagnose(".");
|
|
295
|
-
|
|
296
194
|
const report = toJsonReport(result, { version: "1.0.0" });
|
|
297
|
-
console.log(JSON.stringify(report, null, 2));
|
|
298
|
-
|
|
299
195
|
const counts = summarizeDiagnostics(result.diagnostics);
|
|
300
|
-
console.log(`${counts.errorCount} errors, ${counts.warningCount} warnings`);
|
|
301
196
|
```
|
|
302
197
|
|
|
303
|
-
`react-doctor/api`
|
|
198
|
+
`react-doctor/api` re-exports `JsonReport`, `JsonReportSummary`, `JsonReportProjectEntry`, `JsonReportMode`, plus the lower-level `buildJsonReport` and `buildJsonReportError` builders. See [`packages/react-doctor/src/api.ts`](https://github.com/millionco/react-doctor/blob/main/packages/react-doctor/src/api.ts) for the full types.
|
|
304
199
|
|
|
305
|
-
##
|
|
200
|
+
## Leaderboard
|
|
306
201
|
|
|
307
|
-
|
|
202
|
+
Top React codebases scanned by React Doctor, ranked by score. Updated automatically from [millionco/react-doctor-benchmarks](https://github.com/millionco/react-doctor-benchmarks).
|
|
308
203
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
]
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
```
|
|
204
|
+
<!-- LEADERBOARD:START -->
|
|
205
|
+
<!-- prettier-ignore -->
|
|
206
|
+
| # | Repo | Score |
|
|
207
|
+
| -- | ---- | ----: |
|
|
208
|
+
| 1 | [executor](https://github.com/RhysSullivan/executor) | 96 |
|
|
209
|
+
| 2 | [nodejs.org](https://github.com/nodejs/nodejs.org) | 87 |
|
|
210
|
+
| 3 | [tldraw](https://github.com/tldraw/tldraw) | 76 |
|
|
211
|
+
| 4 | [t3code](https://github.com/pingdotgg/t3code) | 75 |
|
|
212
|
+
| 5 | [mastra](https://github.com/mastra-ai/mastra) | 70 |
|
|
213
|
+
| 6 | [excalidraw](https://github.com/excalidraw/excalidraw) | 69 |
|
|
214
|
+
| 7 | [payload](https://github.com/payloadcms/payload) | 69 |
|
|
215
|
+
| 8 | [better-auth](https://github.com/better-auth/better-auth) | 69 |
|
|
216
|
+
| 9 | [rocket.chat](https://github.com/RocketChat/Rocket.Chat) | 67 |
|
|
217
|
+
| 10 | [typebot](https://github.com/baptisteArno/typebot.io) | 66 |
|
|
324
218
|
|
|
325
|
-
|
|
219
|
+
<!-- LEADERBOARD:END -->
|
|
326
220
|
|
|
327
|
-
|
|
221
|
+
See the [full leaderboard](https://www.react.doctor/leaderboard).
|
|
328
222
|
|
|
329
|
-
|
|
223
|
+
## Resources & Contributing Back
|
|
330
224
|
|
|
331
|
-
|
|
225
|
+
Want to try it out? Check out [the demo](https://react.doctor).
|
|
332
226
|
|
|
333
|
-
|
|
227
|
+
Looking to contribute back? Clone the repo, install, build, and submit a PR.
|
|
334
228
|
|
|
335
229
|
```bash
|
|
336
230
|
git clone https://github.com/millionco/react-doctor
|
|
337
231
|
cd react-doctor
|
|
338
232
|
pnpm install
|
|
339
233
|
pnpm build
|
|
340
|
-
```
|
|
341
|
-
|
|
342
|
-
Run locally:
|
|
343
|
-
|
|
344
|
-
```bash
|
|
345
234
|
node packages/react-doctor/bin/react-doctor.js /path/to/your/react-project
|
|
346
235
|
```
|
|
347
236
|
|
|
237
|
+
Find a bug? Head to the [issue tracker](https://github.com/millionco/react-doctor/issues).
|
|
238
|
+
|
|
348
239
|
### License
|
|
349
240
|
|
|
350
241
|
React Doctor is MIT-licensed open-source software.
|