Creating a Custom, Maintainable React-Scripts Package

Ryan Canfield
4 min readMar 28, 2017


UPDATE: This package is now maintained as complete-react-scripts. All references to helpful-react-scripts have been updated to reflect this.

At Helpful Human, we were looking for a new solution to quickly spin up new projects. We wanted to lean on Facebook’s knowledge of React, Webpack, and best practices surrounding the configuration and maintenance of single page applications. When Facebook released Create React App(CRA), I was excited to be able to harness their knowledge of the build process in my applications.

There was an issue, however.

While create-react-app was an amazing boilerplate to kick off a project with, it didn’t include everything we needed to include in new React projects. By default, CRA sets up your development environment; a build process, Javascript linting, unit tests with Jest, and CSS. This small set of inclusions was purposeful to keep CRA as unopinionated as possible, but, as a result, the functionality lacks much of what we needed to make a fully fledged React application (i.e. state management, routing, and pre-processed styles).

A First Crack At It: A Lesson In Persistence

My initial stab at customizing a CRA application was a mixture of successes and failures. Included in the CRA API is the ability to eject the application. This command essentially severs your reliance/dependency on the React team and allows you to maintain the project yourself.

Using this command, I took control of the application and inserted the changes I needed into my configuration files. Although I could customize a CRA created app, I ran into issues with maintainability. While using this method was considerably faster than setting up a new application from scratch or basic from a boilerplate, it was important to me that the application could still rely on updates from the React team.

Powered with information gleaned from that experimentation, we set out to create a way to harness the power of CRA with the added benefit of including other dependencies we required out of the box. But we needed to do so while maintaining the connection to the original react-scripts package.

After pouring over the CRA documentation, we couldn’t find a maintainable way to overwrite the react-scripts included in CRA with our own package and became a little discouraged. We began questioning the viability of our endeavor.

Finding Our Solution: Custom-React-Scripts

As a last resort, we began researching other possible methods of accomplishing our goal and, in doing so, we came across Custom React Scripts. This discovery was the key to unlocking our ability to harness CRA.

We began reading through how Kitze, the author of custom-react-scripts, enabled the ability to use a custom scripts package and came across an undocumented code snippet in his documentation:

create-react-app my-app --scripts-version custom-react-scripts

Surprisingly, CRA had an undocumented hook built into the API to override the default react-scripts with your own. We couldn’t wait to try it out and, as advertised, custom-react-scripts is a great package for creating CRA created apps with custom additions that are configured through a .env file. While custom-react-scripts is an amazing package for setting up projects with differing requirements, we only needed one specific set up for our team.

Poised with new information, we forked CRA and began editing the react-scripts to include the missing pieces. We added a global state manager in Redux, react-router for managing routes and routing, and Stylus for preprocessing stylesheets.

Once the required packages were configured in our forked version of react-scripts, we gave our new package a name and version number in the package.json and published complete-react-scripts to NPM. It’s important to note that we only published our custom version of react-scripts and not the entirety of the CRA repo. I wanted to make sure I was still able to pull in updates that the React team supplied to CRA and apply them to complete-react-scripts.

It was time to put complete-react-scripts to the test. We ran the snippet that custom-react-scripts uses and replaced custom-react-scripts with our newly created custom-react-scripts.

create-react-app my-app --scripts-version complete-react-scripts

Success! We now had a CRA-created application that pulled our custom script package from npm and had React-Router, Redux, and Stylus out of the box. This was a major step in the right direction and is sure to drastically cut down on the time it takes to spin up a new application.

If you found complete-react-scripts helpful to you, let me know! I’d love to hear how you are using it. Further, if you have suggestions for how I can improve the package I am very open to hearing any ideas you may have!