Run React Doctor automatically in Netlify builds and stop bad React code before it ships.
netlify-plugin-react-doctor is a Netlify Build Plugin that runs during onPreBuild, before your site build command starts. It scans your React source with React Doctor, writes a concise deploy log, shows a Deploy Summary card in Netlify, and can fail the build when findings meet your configured severity gate.
React Doctor catches React-specific issues across state and effects, performance, architecture, security, accessibility, and dead code. Running it in Netlify gives every deploy the same check without asking developers to remember another local command.
Use this plugin when you want to:
- Block deploys with serious React anti-patterns.
- Introduce React Doctor gradually in report-only mode.
- Show React health scores and top findings directly in Netlify deploy details.
- Scan one React app or several app roots in a monorepo.
Install the plugin in your site repository:
npm install -D netlify-plugin-react-doctorAdd it to netlify.toml:
[[plugins]]
package = "netlify-plugin-react-doctor"By default, the plugin scans . during onPreBuild and fails the build when React Doctor reports an error diagnostic.
For an existing app, start in report-only mode:
[[plugins]]
package = "netlify-plugin-react-doctor"
[plugins.inputs]
fail_on = "none"After the first wave of issues is fixed, turn on the default gate:
[[plugins]]
package = "netlify-plugin-react-doctor"
[plugins.inputs]
fail_on = "error"For stricter teams, block on both warnings and errors:
[[plugins]]
package = "netlify-plugin-react-doctor"
[plugins.inputs]
fail_on = "warning"Configure the plugin with plugins.inputs in netlify.toml.
directory: project directory to scan. Defaults to".".projects: optional list of project directories to scan. Defaults to[].fail_on: severity gate for failing the build. Defaults to"error". Allowed values are"error","warning", and"none".skip_without_react: skip cleanly when no React dependency is found. Defaults totrue.lint: run React Doctor lint checks. Defaults totrue.dead_code: run React Doctor dead-code analysis. Defaults totrue.verbose: pass verbose scan behavior through to React Doctor. Defaults tofalse.no_score: skip React Doctor score calculation. Defaults tofalse.respect_inline_disables: respect inlineeslint,oxlint, andreact-doctordisable comments. Defaults totrue.max_findings: maximum number of diagnostics shown in the Deploy Summary details. Defaults to20.output_path: optional path for the full JSON report, relative to the repository root. Defaults to unset.
Example with all common options:
[[plugins]]
package = "netlify-plugin-react-doctor"
[plugins.inputs]
directory = "."
fail_on = "error"
max_findings = 20
no_score = false
skip_without_react = trueEvery plugin input also has an environment-variable fallback. Values in netlify.toml take precedence over environment variables.
REACT_DOCTOR_DIRECTORYREACT_DOCTOR_PROJECTSREACT_DOCTOR_FAIL_ONREACT_DOCTOR_SKIP_WITHOUT_REACTREACT_DOCTOR_LINTREACT_DOCTOR_DEAD_CODEREACT_DOCTOR_VERBOSEREACT_DOCTOR_NO_SCOREREACT_DOCTOR_RESPECT_INLINE_DISABLESREACT_DOCTOR_MAX_FINDINGSREACT_DOCTOR_OUTPUT_PATH
Example:
REACT_DOCTOR_FAIL_ON=none
REACT_DOCTOR_DIRECTORY=apps/web
REACT_DOCTOR_PROJECTS=apps/web,apps/admin
REACT_DOCTOR_MAX_FINDINGS=10REACT_DOCTOR_PROJECTS accepts either a comma-separated list or a JSON array.
For a single React app inside a monorepo, point directory at the app:
[[plugins]]
package = "netlify-plugin-react-doctor"
[plugins.inputs]
directory = "apps/web"For multiple app roots, use projects:
[[plugins]]
package = "netlify-plugin-react-doctor"
[plugins.inputs]
projects = ["apps/web", "apps/admin", "packages/ui"]
fail_on = "error"React Doctor’s own configuration is still respected. You can use react-doctor.config.json for rootDir, ignores, rule severities, categories, surfaces, dead-code settings, and inline-disable behavior.
The plugin runs in onPreBuild, before Netlify executes your site’s build command.
On each run it:
- Normalizes plugin inputs and environment fallback values.
- Runs React Doctor with the configured scan target.
- Builds a structured report from React Doctor diagnostics and score data.
- Calls
utils.status.show()once to render a Deploy Summary card. - Applies the
fail_ongate and callsutils.build.failBuild()when the gate is crossed.
If skip_without_react is enabled and the target is not a React project, the plugin reports a skipped status instead of failing the build.
The Netlify deploy summary includes:
- Pass, fail, or skipped status.
- React Doctor score and score label when available.
- Error and warning counts.
- Affected file count.
- Scanned project metadata.
- Skipped checks, if any.
- Top findings sorted by severity and location.
The plugin uses the classic Build Plugin UI path, utils.status.show(). A richer custom React UI inside app.netlify.com would be a separate Netlify SDK extension that can reuse this plugin’s structured report data.
Set output_path to write the full React Doctor report to disk:
[[plugins]]
package = "netlify-plugin-react-doctor"
[plugins.inputs]
output_path = "reports/react-doctor.json"The path is resolved from the repository root. Create a path under your publish directory if you want the report included in the deployed site.
React Doctor requires Node ^20.19.0 || >=22.12.0. This plugin declares the same engine range.
If your Netlify site uses an older Node version, set a supported version with NODE_VERSION or your preferred Netlify Node version configuration.
The plugin depends on react-doctor directly. It does not run npx during builds.
That is expected when React Doctor finds diagnostics matching fail_on. Use fail_on = "none" to introduce the plugin without blocking deploys.
Scoring can be unavailable if React Doctor cannot reach its score service or if no_score = true is set. Deploy gating is based on diagnostics, not the score.
By default, skip_without_react = true prevents accidental installation from breaking non-React sites. Set it to false if missing React should be treated as a plugin failure.
This plugin currently runs full scans. React Doctor is fast enough for typical onPreBuild usage, and full scans avoid CI diff-base ambiguity on Netlify. Diff mode can be added later with React Doctor CLI parity.
Use a current plugin build. Netlify requires Deploy Summary extraData to be an array, and this plugin emits that shape.
Install dependencies:
bun installRun the verification suite:
bun run test
bun run lint
bun run typecheck
bun run buildRun the local Netlify fixture:
cd test/fixtures/netlify-site
bunx netlify build --offlineThe fixture loads this plugin by relative path:
[[plugins]]
package = "../../.."Published package contents are limited to:
distmanifest.ymlREADME.md
dist/index.js is the Netlify plugin entrypoint.
MIT