Design System creation, from scratch to npmjs.com - Part 1
Tags: webdev, beginners, react, typescript
Published: 2020-05-03 21:41:16

---
title: Design System creation, from scratch to npmjs.com - Part 1
published: true
description:  Mastering the creating of a Design System using Atomic Design with React + TypeScript + Rollup
tags: webdev, beginners, react, typescript
---

Nowadays having a Design System is pretty common. It offers really good advantages: all your projects share the same components and you have a gallery where everyone can see them, even non technical people.

[TLDR; I want my clone!](https://github.com/adancarrasco/design-system-course) 😬

In part 1, I will show you how to setup the project with **React + TypeScript + Rollup**.

By the end of this series you will have a Design System (DS) created using **React + TypeScript + Rollup**, and _not only that_; you will create a DS following [Atomic Design](https://dev.to/adancarrasco/scaling-atomic-design-with-react-oo9) methodology. If you are not familiar with Atomic Design don't worry about it, you'll get it by the end of this series.

Also your DS will be ready to be published to npm, this will allow you to import it in multiple projects and create your products faster than never. 😎

### Prerequisites:

1. Have **npm** installed
2. Have a text editor, preferably **VSCode**
3. Optional: If you want to publish it, you'll need an **npm account**

### Hands on:

Let's start giving this project some shape! I don't intent to do this series really tedious and containing a lot of things that it shouldn't, for that I will be explaining briefly the sections that are not mandatory to know (deeply) to setup the boilerplate. However, if you have any questions you can always drop a comment and I will reply any doubts you may have. 😃

Let's start! 💪

### 1. Create the project folder and init npm

Let's start by creating a folder for our Project. In our project's folder we do:

```sh
npm init -y
```

This command initializes an npm project for us with the default settings.

### 2. Installing the packages we need

Now let's install the packages we need. The following is the list of packages needed to setup the DS boilerplate. It includes packages to work with **React + TypeScript** (and compatibility with it), integrate testing using **Jest + Testing Library**, also includes the minimum packages to setup **Rollup**. As well as the minimum requirements to transpile our code to work with old browsers using **Babel**. Something we normally use in modern projects is a linter, for this we will use **ESlint + Prettier**, and to visualize our DS we will use **Storybook**. The last and optional tool is **EmotionJS** to do our components in a _Styled Components_ way.

- TypeScript: `yarn add -D typescript`
- React: `yarn add -D react react-dom @types/react`
- Rollup: `yarn add -D rollup rollup-plugin-copy rollup-plugin-peer-deps-external rollup-plugin-typescript2 @rollup/plugin-commonjs @rollup/plugin-node-resolve`
- Testing: `yarn add -D @testing-library/jest-dom @testing-library/react @types/jest jest ts-jest`
- For babel (transpiling): `yarn add -D @babel/core babel-loader babel-preset-react-app identity-obj-proxy`
- EmotionJS (Styled Components): `yarn add -D @emotion/core @emotion/styled babel-plugin-emotion`
- For Eslint and Prettier: `yarn add -D eslint eslint-config-prettier eslint-plugin-prettier prettier @typescript-eslint/parser @typescript-eslint/eslint-plugin`
- Storybook: `yarn add -D @storybook/react`

After installing the packages, we are set to start doing some configuration. ✨

### 3. Adding some scripts to run our project

Now in our `package.json` we need to put some scripts to let us **build, test and visualize** our components.

```json
    "build": "rm -rf ./build && rollup -c",
    "lint": "eslint '*/**/*.{js,ts,tsx}' --quiet --fix",
    "storybook": "start-storybook -p 6006",
    "storybook:export": "build-storybook",
    "test": "jest",
    "test:watch": "jest --watch"
```

### 4. Setting up our packages configurations
   All of the following need a configuration file to know how they should operate, depending on each project/team rules the config may change. For this example I will leave it as generic as possible, trying to affect the less I can. I will put at the beginning of the section the name of the config file for each of them.

Most of the properties in each config file are explained in the name of the prop, for some that are not obvious I will add a brief description at the end of the section. 😌

#### TypeScript

`tsconfig.json`

```json
{
  "compilerOptions": {
    "declaration": true,
    "declarationDir": "build",
    "module": "esnext",
    "target": "es5",
    "lib": ["es6", "dom", "es2016", "es2017"],
    "sourceMap": true,
    "jsx": "react",
    "moduleResolution": "node",
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "typeRoots": ["./node_modules/@types", "jest"],
    "types": ["jest"]
  },
  "include": ["src/**/*"],
  "exclude": [
    "node_modules",
    "build",
    "src/**/*.stories.tsx",
    "src/**/*.test.tsx"
  ]
}
```

In summary this file will transpile our TypeScript into JavaScript using as target: es5, will ignore some folders (exclude), and will configure things for testing (typeRoots), using jsx for React, building everything in `build`'s directory.

#### Rollup

`rollup.config.js`

```JavaScript
import peerDepsExternal from 'rollup-plugin-peer-deps-external'
import resolve from '@rollup/plugin-node-resolve'
import typescript from 'rollup-plugin-typescript2'
import commonjs from '@rollup/plugin-commonjs'

import packageJson from './package.json'

export default [
  {
    input: 'src/index.ts',
    output: [
      {
        file: packageJson.main,
        format: 'cjs',
        sourcemap: true,
      },
      {
        file: packageJson.module,
        format: 'esm',
        sourcemap: true,
      },
    ],
    plugins: [
      peerDepsExternal(),
      resolve(),
      commonjs(),
      typescript({ useTsconfigDeclarationDir: true }),
    ],
  },
]
```

This one is a little bit more extended, in this case we are telling rollup to use **peerDepsExternal** this means that if the project importing this DS already has installed the packages inside peerDepsExternal, they won't be included as part of this package (DS) import. It also setups the _output_ format as CommonJS (csj) and ES modules (esm) (for older and modern browsers respectively). Using some _plugins_ to do the transpilation for us.

#### Jest

`jest.config.js`

```JavaScript
module.exports = {
  roots: ['./src'],
  setupFilesAfterEnv: ['./jest.setup.ts'],
  moduleFileExtensions: ['ts', 'tsx', 'js'],
  testPathIgnorePatterns: ['node_modules/'],
  transform: {
    '^.+\\.tsx?$': 'ts-jest',
  },
  testMatch: ['**/*.test.(ts|tsx)'],
  moduleNameMapper: {
    // Mocks out all these file formats when tests are run
    '\\.(jpg|ico|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': 'identity-obj-proxy',
    '\\.(css|less|scss|sass)$': 'identity-obj-proxy',
  },
}
```

This file is defining the files we are going to test, the format and how we are going to call them (_testMath + moduleFileExtensions_), how jest should interpret them (_transform_), also includes the folders that should be ignored (_testPathIgnorePatterns_) and finally some files/resources that will/can be mocked (_moduleNameMapper_). It also contains additional setup so we don't need to add it in all of our tests.

`jest.setup.ts`

```TypeScript
import '@testing-library/jest-dom'
```

#### ESlint + Prettier

`.eslintrc.js`

```JavaScript
module.exports = {
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaVersion: 2020,
    sourceType: 'module',
    ecmaFeatures: {
      jsx: true,
    },
  },
  settings: {
    react: {
      version: 'detect',
    },
    extends: [
      'plugin:react/recommended',
      'plugin:@typescript-eslint/recommended',
      'prettier/@typescript-eslint',
      'plugin:prettier/recommended',
    ],
    rules: {},
  },
}
```

Defines where the VSCode (in this case) will show you some errors, you can mix it up with TS Config to mark them as errors as well. In this file we have some recommended Lint rules for the tools we are using as React + TypeScript + Prettier.

`.prettierrc.js`

```JavaScript
module.exports = {
  semi: false,
  trailingComma: 'all',
  singleQuote: true,
  printWidth: 100,
  tabWidth: 2,
}
```

This file is just matter of style for your code, if you want to use _trailingCommas_ or not, _singleQuotes_ for strings, your _tabWidth_, etc.

#### Storybook

`.storybook/main.js`

```JavaScript
const path = require('path')

module.exports = {
  stories: ['../src/**/*.stories.tsx'],
  // Add any Storybook addons you want here: https://storybook.js.org/addons/
  addons: [],
  webpackFinal: async (config) => {
    config.module.rules.push({
      test: /\.(ts|tsx)$/,
      loader: require.resolve('babel-loader'),
      options: {
        presets: [['react-app', { flow: false, typescript: true }]],
      },
    })
    config.resolve.extensions.push('.ts', '.tsx')

    return config
  },
}
```

In this case we setup the name we will give to our _stories_ (code where we will demo the usage of our components), the extensions and wether you are using Flow or TypeScript.

#### EmotionJS (Optional)

`.babelrc`

```JSON
{
  "env": {
    "production": {
      "plugins": ["emotion"]
    },
    "development": {
      "plugins": [["emotion", { "sourceMap": true }]]
    }
  }
}
```

This is a small setup to tell our project how it will transpile our Emotion components.

### End of part 1

In general all those config files have pretty much the same structure, it can be tricky at first but once you get familiar with the structure all of them are really alike.

I hope you enjoyed the first part of this series. IMO, the setup of the project is the more tedious, however the funniest parts are coming. 🎉

Thanks for reading, if you have any questions you can @ me in Twitter at [@adancarrasco](https://twitter.com/adancarrasco). See you in part 2!