# Extension points — react/create-react-app

> Canonical page: https://codevetter.com/unpack/create-react-app/extension-points

# Extension points — react/create-react-app

Scanned commit 6254386531d263688ccfa542d0e628fbc0de0b28 (2025-02-14). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

CRA's extension model is deliberate and narrow: custom templates, a replaceable react-scripts package (--scripts-version), env vars, package.json fields (proxy, homepage, browserslist, jest, babel), and finally eject. There is no in-process plugin registry. The practical plug-in points inside the repo are the webpack config factory, the Jest config factory, babel-preset-react-app's create() options, and ESLint's optional plugin detection. Community tools (CRACO, react-app-rewired) patch these from outside because the project refuses a first-party override API.
- Templates are the supported product extension. A template package must be named cra-template-* (or scoped) and contain template.json plus a template/ directory. template.json keys merged by init.js are package.json fields: dependencies, scripts, eslintConfig, babel, jest, browserslist. Any extra files under template/ are copied verbatim. — [packages/react-scripts/scripts/init.js#L60-180](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/react-scripts/scripts/init.js#L60-L180) [packages/cra-template/template.json#L1-40](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/cra-template/template.json#L1-L40) [docusaurus/docs/custom-templates.md#L1-40](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/docusaurus/docs/custom-templates.md#L1-L40)
- --scripts-version replaces the entire toolchain package. A fork must provide bin/react-scripts.js and scripts/init.js, start.js, build.js, test.js. The CLI does not feature-detect; it only installs and executes init.js. — [packages/create-react-app/createReactApp.js#L280-450](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/create-react-app/createReactApp.js#L280-L450) [packages/react-scripts/bin/react-scripts.js#L1-80](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/react-scripts/bin/react-scripts.js#L1-L80)
- webpack.config.js exports a factory function of webpackEnv. Internal extension is editing that factory (or ejecting a copy). There is no plugins array exposed to package.json. Advanced-configuration docs point users at environment variables rather than a config file. — [packages/react-scripts/config/webpack.config.js#L40-100](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/react-scripts/config/webpack.config.js#L40-L100) [docusaurus/docs/advanced-configuration.md#L1-40](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/docusaurus/docs/advanced-configuration.md#L1-L40)
- Environment extension surface (read by env.js and start.js): PORT, HOST, HTTPS, SSL_CRT_FILE, SSL_KEY_FILE, BROWSER, BROWSER_ARGS, PUBLIC_URL, BUILD_PATH, GENERATE_SOURCEMAP, INLINE_RUNTIME_CHUNK, IMAGE_INLINE_SIZE_LIMIT, FAST_REFRESH, CHOKIDAR_USEPOLLING, TSC_COMPILE_ON_ERROR, ESLINT_NO_DEV_ERRORS, DISABLE_ESLINT_PLUGIN, DISABLE_NEW_JSX_TRANSFORM, WDS_SOCKET_HOST, WDS_SOCKET_PATH, WDS_SOCKET_PORT, DANGEROUSLY_DISABLE_HOST_CHECK, CI, and REACT_APP_*. — [packages/react-scripts/config/env.js#L70-140](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/react-scripts/config/env.js#L70-L140) [packages/react-scripts/scripts/start.js#L40-160](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/react-scripts/scripts/start.js#L40-L160) [docusaurus/docs/advanced-configuration.md#L1-50](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/docusaurus/docs/advanced-configuration.md#L1-L50)
- package.json fields honored without eject: proxy (string or object consumed by prepareProxy), homepage (feeds publicPath via paths.js), browserslist, and optional jest/babel overrides that get merged but are only partially respected — createJestConfig ignores most user keys unless they were written by eject. Users commonly discover this limitation. — [packages/react-scripts/config/paths.js#L90-150](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/react-scripts/config/paths.js#L90-L150) [packages/react-dev-utils/WebpackDevServerUtils.js#L200-320](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/react-dev-utils/WebpackDevServerUtils.js#L200-L320) [packages/react-scripts/scripts/utils/createJestConfig.js#L40-120](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/react-scripts/scripts/utils/createJestConfig.js#L40-L120)
- babel-preset-react-app's create(options) is the Babel extension point inside the monorepo. webpack and Jest both call it with absoluteRuntime, flow flags, and helpers. babel-plugin-named-asset-import is injected here so SVG ReactComponent imports work. Custom presets in the app are not loaded unless the user ejects or replaces the preset. — [packages/babel-preset-react-app/create.js#L1-100](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/babel-preset-react-app/create.js#L1-L100) [packages/babel-preset-react-app/index.js#L1-30](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/babel-preset-react-app/index.js#L1-L30) [packages/babel-plugin-named-asset-import/index.js#L1-50](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/babel-plugin-named-asset-import/index.js#L1-L50)
- ESLint extension is eslintConfig in package.json of the generated app, which extends react-app and optionally react-app/jest. Adding rules works; changing the parser for TS is automatic only when typescript and the parser package are installed. The config file exports a function so it can conditionally require plugins. — [packages/eslint-config-react-app/index.js#L1-80](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/eslint-config-react-app/index.js#L1-L80) [packages/cra-template/template.json#L10-40](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/cra-template/template.json#L10-L40)
- Jest transformers are extension points for non-JS assets: cssTransform returns an empty module, fileTransform stringifies filenames (and special-cases SVG for ReactComponent). New asset types require a new transform plus a moduleNameMapper entry in createJestConfig. — [packages/react-scripts/config/jest/cssTransform.js#L1-25](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/react-scripts/config/jest/cssTransform.js#L1-L25) [packages/react-scripts/config/jest/fileTransform.js#L1-60](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/react-scripts/config/jest/fileTransform.js#L1-L60) [packages/react-scripts/scripts/utils/createJestConfig.js#L80-150](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/react-scripts/scripts/utils/createJestConfig.js#L80-L150)
- react-error-overlay is replaceable only by eject or by aliasing the module. It exposes a small runtime API (listen, report, dismiss, startReportingRuntimeErrors) used by webpackHotDevClient. Editing overlay UX means changing that package and rebuilding it (npm run build). — [packages/react-error-overlay/package.json#L1-35](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/react-error-overlay/package.json#L1-L35) [packages/react-dev-utils/webpackHotDevClient.js#L1-50](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/packages/react-dev-utils/webpackHotDevClient.js#L1-L50)
- Docusaurus docs extension is file-based: drop an md file in docusaurus/docs and add it to sidebars.json. swizzle script exists for theming. This does not affect the CLI. — [docusaurus/website/sidebars.json#L1-60](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/docusaurus/website/sidebars.json#L1-L60) [docusaurus/website/package.json#L1-30](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/docusaurus/website/package.json#L1-L30)
- Supported alternatives to a plugin API, as documented, are: composing libraries inside src/, using a custom template, forking react-scripts, or ejecting. The docs page alternatives-to-ejecting.md is the product decision record: CRA will not grow an overrides config. — [docusaurus/docs/alternatives-to-ejecting.md#L1-40](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/docusaurus/docs/alternatives-to-ejecting.md#L1-L40) [CONTRIBUTING.md#L1-40](https://github.com/react/create-react-app/blob/6254386531d263688ccfa542d0e628fbc0de0b28/CONTRIBUTING.md#L1-L40)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
