Building a React Components Library

Part 1 — The library itself and local development setup

Tomasz Fiechowski
Aug 13 · 6 min read

Sharing is caring. In software, sharing also leads to… decoupling!

  • Have you ever had your codebase flooded with so many components that they were basically screaming to be extracted?
  • Do you have an idea for a cool UI library or want to share your components across multiple projects?
  • Or do you just want to learn how to create component libraries and publish them to npm?

All these cases are covered in this tutorial. It will be a series of four pieces, each covering a different part of the process.

Tutorial Parts

Note: Stay tuned for the next pieces. As soon as they’re out, the list will be updated with corresponding links.

We will build it from scratch, from bare bones. It’s far easier than it sounds!

Technology Stack

Let’s take a look at the complete list of the technologies we will use in the project:

Preparing the Project

We are starting from bare-bones, so let’s set up some basics to create a skeleton for the project.


First, create a directory for the library. Go inside and initialize the npm package:

Yeah, npm init.

I told you we are building it from scratch! By running npm init with a -y flag, package.json is created without answering all those boring setup questions. The package name will default to the directory name.

Core dependencies: React and Emotion

We will use React and Emotion in our library, so let’s install and add them as peerDependencies.

Why peer? It tells npm/yarn about the compatibility of our dependencies and also helps us later with preventing them from being bundled into the final package. Bundling the whole React into your library is a pretty bad idea, believe me.

Let’s run the following command to install the core dependencies:

npm install --save-dev react react-dom @emotion/core @emotion/styled

Later, manually update the peerDependencies, replacing versions of the libraries to match the major one. Our package.json should now look like this:


Live development with Styleguidist

Let’s add Styleguidist as we will be using it for the development with live reloading and preview of the components:

npm install --save-dev react-styleguidist webpack

To make Styleguidist work, we need to install Babel with some presets and create config files for both Babel and Styleguidist.

To install all Babel-required packages, run:

Now, we need to create the Babel config file, .babelrc, in the root directory of the project. Let’s add the installed presets there:


The final step is to set up Styleguidist’s internal webpack instance to use our Babel config for loading the components properly.

Let’s create styleguide.config.js with the following content:


We’re ready to launch the live development server now!

Add the ”start”: “styleguidist server” script to your package.json and run npm start.

Enter http://localhost:6060 and you should see something like this:

It’s running! But wait, it’s empty…

Creating Components

We have the skeleton of the project and development environment fully set up, time to create some components.

The sources of the components will be laid out in the src/components directory. Pretty straightforward.

Let’s create the following structure in the project:

We will start by making a really simple button.

Copy the following code to src/components/Button.js:


Enter http://localhost:6060 again and… drum roll … we see that the button has been found!

It doesn’t show anything yet, but Styleguidist makes it easy to preview and describe the components.

Let’s add the markdown file next to the Button.js and, inside, type:


We can mix Markdown with JavaScript/React code here to show the examples and descriptions easily.

After adding the let’s restart Styleguidist (npm start) and refresh the docs (only needed when adding .md files, it’s hot-reloaded otherwise), we should now see:

We have created our first component, have a development environment with live preview, and the export-ready documentation at the same time.


Let’s Add Some Style

Our button is plain and boring. Writing in plain CSS is not convenient; let’s use Emotion to have some CSS-in-JS capabilities to write styles easily.

Note: If you want to use component selectors, you need to install a Babel plugin to handle the Emotion styles preprocessing.

To do it, run npm install --save-dev babel-plugin-emotion and add the plugin to .babelrc: “plugins”: [“emotion”].

Let’s sprinkle some CSS on the button now:


My name is Button, The Button.

Adding More Components and Utilities

When the library grows, it’s better to share common parts between the components.

Let’s extract some styles from the Button component and put them in a separate file: src/config/styles.js.

To create CSS that can be shared across components, we will use the css function from Emotion.


We may now import and add the styles to the button:


We improved one thing, but now another went bad…

See that from '../config/styles'? Imagine having more levels of nesting…

Absolute Imports

Let’s change relative imports to absolute ones.

Babel comes to the rescue once again with a module resolver plugin.

Let’s install it with npm install babel-plugin-module-resolver and add it to plugins in .babelrc like this:


Shoutout to my friend FatFisz (@GitHub) for contributing a lot to that plugin!

The root option tells Babel where to look for the modules.

It’s like specifying an additional node_modules directory. Now, we can import things from src. The ugly '../config/styles' in Button becomes:


Similarly, we can directly import components from other components.

For example, if we wanted to import Button in a different component, we would do it like this (as the components directory is a direct child of src):


We’ve created the React component library from scratch!

We’ve added Styleguidist to set up the development environment and Babel to transform our React code properly. Then we created our first component, styled it with Emotion, and extracted some shared CSS.

Finally, we improved the readability of the code by enabling absolute imports.

We’ve done a good job! That’s it for this part.

The full code is available in the GitHub repository. You can check out the part1 tag (git checkout part1) to see the full example for this part.

Better Programming

Advice for programmers.

Tomasz Fiechowski

Written by

Software engineer & Team leader @Codility

Better Programming

Advice for programmers.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade