How to set up a React application from scratch in 36 easy steps.

Tim Maloshtan
May 21 · 8 min read

*record scratch* “Hello, my name is ${userName}, and you are probably wondering how I ended up here…”

My guess is the following. You got a million-dollar startup idea or sudden enthusiasm to try that new exciting React concept and needed to quickly spin up an app and you had one of two reasons to search for this guide:

  • Maybe you were too tight on disk space to have create-react-app installed every known npm package and a kitchen sink to your neat little project.
  • Maybe, on the other hand, the thought of having to configure your build on your own promised such tedium and boredom, that you were about to drop it altogether and go stare in the mirror and watch your hair grow. At least that would be more fun.

I’ve been there myself. Which is why I decided to flash out a guide to set up a modern and nimble React app. There’s going to be quite a few simple steps spiked with memes and gifs.

Full disclosure: I am doing this to learn more by sharing what I already know. So if you know that something I’ve done here is dead wrong or can be done better, let me know in the comment section, and I will update accordingly… or report you for abuse😂😭

This guide assumes:

  • You having a computer
  • That computer having node and npm installed
  • You having familiarity with terminal commands and JavaScript


  1. Clone this repo:
  2. npm i; npm start
  3. Develop your react app

1. Bust out your favorite CLI and type in following commands:

mkdir your-project
cd your-project
touch index.html

NOTE: mkdir creates a directory with a given name, cd steps into it, touch creates a file with a given name. Feel like a hacker already?

2. Open your preferred code editor and fill up that index.html . You can save a lot of calories doing that if you use snippets in VS Code. Just type ! and smack ‘Tab’ button:

Save dat energy!

3. Create the first JavaScript file. Run these commands in your terminal:

mkdir src
touch src/index.js

NOTE: Assuming you are in the project’s main folder, this will create src subdirectory.

4. Write some JavaScript there:

5. To run our newly created Javascript on our page add a script element between the body tags of your page:

<script src="src/index.js"></script>

At this stage your project structure looks like this:


and does this:

Now you don’t want to be stuck writing all your JavaScript in one file or adding scripts for each .js file. So you need to bundle it up. Let’s go from simple markup and scripts into installing your module bundler and configuring it.

6. Initialize npm project by running this command and following the prompts:

npm init

NOTE: It will have created package.json file for you to describe your project and keep the list of its dependencies.

7. Create .npmrc file and configure it in a way that your installs generate package-lock.json only when you tell it to do so:

touch .npmrc

NOTE: package-lock.json ensures that you install the same versions of your dependencies each time for consistency.

NOTE: If you go along you will notice creating a lot of files ending with rc. Usually, they configure their corresponding utilities: .babelrc, .eslintrc, etc.

8. Install webpack locally by running:

npm i -D webpack

NOTE: -D flag saves it to your project’s devDependencies

If you try to run it now by typing in:


you’ll get a notification:

9. Just agree and let them do their thing.

10. Eventually, you’ll get tired of typing node_modules/.bin/... each time. Make it a little more workable by adding npm scripts in your package.json. Update scripts property accordingly:

Once you will have configured your build, you will be able to trigger it by running:

npm run build

11. Create the dreaded webpack.config.js :

touch webpack.config.js

NOTE: This file exports a configuration that webpack uses to build your bundle.

12. Tell it where to enter your app to start building a dependency graph and where to put the resulting bundle:

13. It is also convenient to command webpack to generate html file into your bundle either from default template or the one you provide. We use html-webpack-plugin for that:

npm i -D html-webpack-plugin

14. Configure that bad boy:

Now it will grab your index.html, hook up whatever bundle you’ve created to it, and emit a file with the same name inside our build folder.

15. Since generated bundle is inserted automatically, you can drop this line from index.html:

<script src="src/index.js"></script>

Learn more about this plugin here.

NOTE: All the way up to here I was trying to break build process by introducing modern JS features like arrow functions and ES6 imports into my code. But it wouldn’t fail. Turns out that webpack does not require a config file by default as of version 4. But we will still add a transpiler just for learning purposes. You live and you learn!

Webpack uses loaders to transform files from something into something else. You need to set up rules for that with a test property that applies a regular expression to a filename and use property that specifies the sequence of loaders to be applied.

16. Let’s install babel-loader and related packages to turn your arrow functions, imports, async/await’s, destructuring, etc. into prehistoric gobbledygook that old browsers understand.

npm i -D babel-loader @babel/core @babel/cli @babel/runtime @babel/plugin-proposal-class-properties @babel/preset-env @babel/plugin-transform-runtime

17. Back to webpack.config.js we go:

18. Create .babelrc file and tell babel-loader what to do with all those libraries:

touch .babelrc

If you try running a bundling process now, you will see a warning like this one:

The thing is that webpack uses a lot of optimizations depending on the environment you are working in. There are plenty of default settings for both development and production modes. For the purposes of this guide, we will make sure that webpack knows which environment it’s currently working in and sets up your dev tools accordingly.

The dev tool in question is source maps. If you run into an error in a minified code without them, you are pretty much done. Here’s footage of you figuring out what’s going on when all your application is squished into one file with one letter variable names and no whitespace or formatting:

Source maps, on the other hand, provide you with compartmentalized, either inline or by files, representation of your codebase for easy debugging.

19. Webpack comes with a dedicated development server. Install it by running:

npm i -D webpack-dev-server

20. Add devServer property to your config object to specify server behavior:

21. Add a script to package.json to run your development server:

Now with just a simple:

npm start

you will get development server with live reloading running on http://localhost:8080/.

Neat huh?

22. How do you let webpack aware of the value of env? Simple. Just change module.exports from an object to a function that takes env as an argument and returns a configuration object. Let’s discern the value of devtool property based on that:

It’s time to take a little breather for an inventory.

Your project tree looks like this now:


You can write your code using modern JavaScript features, compile it into a bundle with source maps for convenient debugging and serve it with live reloads. If by now you are happy to just tinker with browser JavaScript locally, knock yourself out and skip the rest of the guide.

If however, your mama didn’t raise no quitter, let’s reactify this.

23. Install react and react-dom:

npm i -S react react-dom

24. Add a mounting node to your html template:

<div id="app"></div>

NOTE: That id can be whatever you like by the way. “app” value is arbitrary.

25. Modify src/index.js to make use of React framework:

babel is very confused right about now with you using that HTML looking syntax is .js file.

Your app is all grown up now and it’s time to educate it about JSX. It’s is better if it learns it from you than on the streets.

26. Install the corresponding babel preset:

npm i -D @babel/preset-react

27. Add it to .babelrc:

And we already added a rule for files with .jsx extension to webpack.config.js

28. Obviously visual component is important and we will take care of styling our app. And also there is an artist in each and every one of us…

npm i -D node-sass css-loader sass-loader style-loader

29. Add a rule for .scss modules into your webpack.config.js :

NOTE: Make sure to preserve the order of loaders. It is actually inverted: first sass-loader loads Sass/SCSS file and compiles it to CSS, then css-loader resolves the import, and finally style-loader adds CSS to the DOM by injecting a <style> tag.

30. Add some basic styling:

touch src/style.scss

31. Import style rules into index.js:

Things are looking up, aren’t they?

By now you are probably reciting one of the great philosophers of our time:

Are we there yet? (Donkey)

Almost, I promise. Let’s slap on some linting, and you’ll be well on your way.

32. Install linting tooling:

npm i -D eslint babel-eslint eslint-config-airbnb eslint-plugin-import eslint-plugin-jsx-a11y eslint-plugin-react

33. Configure linting rules and mute some annoying ones:

touch .eslintrc

34. Install pre-commit to run linting before committing:

npm i -D pre-commit

35. Add an npm script for linting and make sure it runs before commits:

36. Tweak index.js to comply with accessibility requirements:

Aaaand done! If you have made it this far, please let me know:

  • If something essential is missing from this starter pack for smooth react development.
  • If you would like to know how to add Redux to this starter pack and set a convenient project structure.

No long goodbyes. Thanks for sticking it out with me!

Source code for the starter pack here.