Integrating Gatsby, Tailwind, and Storybook
Tags: javascript, gatsby, tailwindcss, storybook
Published: 2019-11-10 13:25:19

A guide to the quick and easy setup of Storybook and Tailwind within Gatsby.

Gist: [https://gist.github.com/romansorin/916cf914b90456f0ea584847d0db2db7](https://gist.github.com/romansorin/916cf914b90456f0ea584847d0db2db7)

One of my current projects is dedicated to documenting and describing UX research that I’ll be conducting within the coming weeks/months. In building this project, I got the idea to use Tailwind, Gatsby, Firebase, and Storybook to get my hands dirty whilst still being able to build the app without too much effort.

In trying to do so, I had difficulty finding any sort of guide which covers how to use Tailwind and Gatsby with Storybook and found that traditional setup resulted in Tailwind styling to not work correctly or be loaded in. After coming to a working setup, I figured I'd release a guide to help others interested in integrating these.

# Initial Setup

Start by creating a new Gatsby project:
```bash
    npm install -g gatsby-cli
    gatsby new tailwind-gatsby-storybook
    cd tailwind-gatsby-storybook
    gatsby develop
```
### Dependencies

You'll need to install the associated Tailwind and Storybook dependencies, as per the [Gatsby documentation](https://www.gatsbyjs.org/docs/). We'll start with installing [TailwindCSS](https://tailwindcss.com/), the utility-first CSS framework that is, in my opinion, the best framework out there.

## Tailwind setup:
```bash
    npm install tailwindcss --save-dev
    npx tailwind init
```bash
This will install the framework and create a `tailwind.config.js` file, which can be used to theme and extend the framework.

Next, we'll setup PostCSS to work with Gatsby and Tailwind directive loading:
```bash
    npm install --save gatsby-plugin-postcss
```bash
In your `gatsby-config.js` file, modify the plugins property to include this plugin:
```js
    // gatsby-config.js
    
    plugins: [`gatsby-plugin-postcss`],
```
Create a `postcss.config.js` file in the root of your project:
```js
    // postcss.config.js
    
    module.exports = () => ({
      plugins: [require("tailwindcss")],
    })
```
Now that the initial setup is completed, we can install Storybook for Gatsby. Later in the tutorial, we'll create/modify our `app.css` file (or whatever you intend on using) to utilize the Tailwind directives.

## Storybook

Start by making sure you have the CLI installed. In the root of your project, run:
```bash
    npm install -g @storybook/cli
    sb init
```
This will create a `.storybook` folder in your project root which will contain storybook config files:
```bash
    .storybook/
    	- addons.js
    	- config.js
```
Edit the `config.js` file found in the `.storybook` directory:
```js
    import { configure } from '@storybook/react'
    import { action } from '@storybook/addon-actions'
    
    // We will address this later.
    import '../src/components/layout.css'
    
    // automatically import all files ending in *.stories.js
    configure(require.context('../src', true, /\.stories\.js$/), module)
    
    // Gatsby's Link overrides:
    // Gatsby defines a global called ___loader to prevent its method calls from creating console errors you override it here
    global.___loader = {
      enqueue: () => {},
      hovering: () => {}
    }
    // Gatsby internal mocking to prevent unnecessary errors in storybook testing environment
    global.__PATH_PREFIX__ = ''
    // This is to utilized to override the window.___navigate method Gatsby defines and uses to report what path a Link would be taking us to if it wasn't inside a storybook
    window.___navigate = pathname => {
      action('NavigateTo:')(pathname)
    }
```
**Note:** It's important to pay attention to the directory specified in the `configure(require.context(), module)` statement. This will recursively scan the specified directory and import all `*.stories.js` files. For this tutorial (and as recommended by Gatsby docs) we've moved all stories into `src`.

Next, create a `webpack.config.js` within the `.storybook` directory:
```js
    const path = require('path')
    
    module.exports = ({ config }) => {
      config.module.rules.push({
        test: /\.css$/,
        use: [
          // Loader for webpack to process CSS with PostCSS
          {
            loader: 'postcss-loader',
            options: {
              sourceMap: true,
              config: {
                path: './.storybook/'
              }
            }
          }
        ],
    
        include: path.resolve(__dirname, '../')
      })
      // Transpile Gatsby module because Gatsby includes un-transpiled ES6 code.
      config.module.rules[0].exclude = [/node_modules\/(?!(gatsby)\/)/]
    
      // use installed babel-loader which is v8.0-beta (which is meant to work with @babel/core@7)
      config.module.rules[0].use[0].loader = require.resolve('babel-loader')
    
      // use @babel/preset-react for JSX and env (instead of staged presets)
      config.module.rules[0].use[0].options.presets = [
        require.resolve('@babel/preset-react'),
        require.resolve('@babel/preset-env')
      ]
    
      config.module.rules[0].use[0].options.plugins = [
        // use @babel/plugin-proposal-class-properties for class arrow functions
        require.resolve('@babel/plugin-proposal-class-properties'),
        // use babel-plugin-remove-graphql-queries to remove static queries from components when rendering in storybook
        require.resolve('babel-plugin-remove-graphql-queries')
      ]
    
      // Prefer Gatsby ES6 entrypoint (module) over commonjs (main) entrypoint
      config.resolve.mainFields = ['browser', 'module', 'main']
    
      return config
    }
```
This is almost identical to the configuration provided at the [Gatsby docs](https://www.gatsbyjs.org/docs/visual-testing-with-storybook/), but includes the PostCSS loader. If you're using Typescript in your project, refer to the Gatsby docs on proper setup.

At this point, your project structure will look something like this (only including relevant files):
```bash
    tailwind-gatsby-storybook/
    ├── .storybook/
    	├── addons.js
    	├── config.js
    	├── taildwind.config.js
    ├── src/
    	├── components/
    	    ├── stories/
                ├── Examples.stories.js
    ├── tailwind.config.js
    ├── postcss.config.js
    ├── gatsby-config.js
    
```
Note that we haven't created the necessary CSS files for directives yet, so that is not included here.

# Final Setup

We'll now need to create our app's main CSS file to hold our directives in, and make sure it's referenced correctly in our config files.

Start by creating a `layout.css` file (or similarly named):
```bash
    touch ./src/components/layout.css
```
Modify the file:
```css
    @tailwind base;
    
    @tailwind components;
    
    @tailwind utilities;
```
Check that the reference to this file in `.storybook/config.js` is set correctly:
```js
    import '../src/components/layout.css'
```
This should point directly to the file.

And that's it! You can now build Storybook stories and use Tailwind + React inside of it.

# Conclusion

Given the popularity and recent growth of things like Gatsby, Tailwind, and Storybook, I figured it would pay off to be able to integrate all of these properly. Having found both Tailwind and Gatsby to be super helpful, rapid tools for development and MVP in isolated environments, this integration with Storybook for UI testing/style guide can increase the perceived productivity tenfold.

### You can find me on:

- Twitter: [https://twitter.com/romansorinn](https://twitter.com/romansorinn)
- Portfolio: [https://romansorin.com](https://romansorin.com)
- GitHub: [https://github.com/romansorin](https://github.com/romansorin)