Using Storybook 6.1 with Next.js and Emotion 11 - Advanced usage and best practices
Tags: storybook, nextjs, react, vercel
Published: 2021-01-17 14:11:30

The [Next Right Now](https://github.com/UnlyEd/next-right-now) boilerplate recently got an interesting upgrade!


# Overview

We've added Storybook side-by-side with our Next.js application. It took us about 4 days of intensive work.

We had never used Storybook in the past, and we were looking for a Design System to help our designers and developers build components in a better way, with proper documentation, functional testing, accessibility testing, and interact with our components. Storybook helped us achieve all of that - and even a bit more.

> While this work has been done on Next Right Now, any Next.js project can benefit from it.
>
> Check out the [Pull Request](https://github.com/UnlyEd/next-right-now/pull/251) and [documentation](https://unlyed.github.io/next-right-now/guides/storybook/) to learn more about it.

Check out the result on our [Storybook demo](https://nrn-v2-mst-aptd-at-lcz-sty-storybook.vercel.app/?path=/story/next-right-now-welcome-to-nrn--page).

# Main features

- Compatible with TypeScript
- Compatible with Emotion 10/11, useful if you use Emotion yourself, or libs using Emotion
- Next.js router (decorator)
- Compatible with Sentry
- Compatible with node-related libs
- Compatible with CSS Modules
- Static site automatically deployed on Vercel, using GitHub Actions
- Automated tests using Cypress, to make sure you get warned if you accidenly break your static site
- Support for i18next and Locize provider (fetched and cached upon build)

# Methodology and learnings

## Initial configuration

It wasn't easy. The most difficult part was Emotion/Node.js, because it required some Webpack/Babel tricks with solutions and workarounds splattered all over the web. Emotion was quite a pain in particular, because their TS types clash between v10 and v11. Next Right Now had been upgraded to v11 last week, but some libraries we use are still using v10, which creates a few inconsistencies, even after configuring Webpack and Babel as recommended. 

Definitely not something easy to do. It took us about one and half day of work to get it right. Also, we directly integrated automated deployments (CI/CD) using Vercel and GitHub Actions. That part was easy because we have quite a lot of experience with those already.

## Build a solid Storybook foundation

Once all the pieces had been properly configured, we started looking at the Storybook ecosystem. We wasted 2 good hours trying to use `knobs` before we figured it wasn't the recommended way to do things anymore. (Replaced by `controls` in v6)

The https://storybook.js.org/addons/ was great to get an overview of all existing addons, and we went through the whole list, to look at all those that were promising. Eventually, we selected 8 officials and 5 community-maintained. Checking all of them took us another day.

```
    // Officials
    "@storybook/addon-a11y": "6.1.14",
    "@storybook/addon-actions": "6.1.14",
    "@storybook/addon-console": "1.2.2",
    "@storybook/addon-essentials": "6.1.14",
    "@storybook/addon-google-analytics": "6.1.14",
    "@storybook/addon-jest": "6.1.14",
    "@storybook/addon-links": "6.1.14",
    "@storybook/addon-storysource": "6.1.14",

    // Community
    "storybook-addon-designs": "5.4.3",
    "storybook-addon-next-router": "2.0.3",
    "storybook-addon-performance": "0.14.0",
    "storybook-css-modules-preset": "1.0.5",
    "storybook-mobile": "0.1.29",
``` 

We documented them all in the [`.storybook/main.js` file](https://github.com/UnlyEd/next-right-now/blob/e5aba8eaf02918d9506008ee1f11c38954fedc86/.storybook/main.js#L53-L196)

Those addons were "must-haves" to us. Eventually, we disabled `storysource` and we don't actually use `performance` much yet, but it looks promising.

> Storybook has a special `essentials` package regrouping all the ["essential" features](https://storybook.js.org/addons/essentials), it definitely helped us! _(but we're greedy and wanted more!)_

## Mock our app behavior

And then, we had to mock stuff around, using Decorators, configuring i18n with Locize so our components could behave in Storybook the same way they behave in Next Right Now. Overall, it wasn't so hard, but [took time to get right](https://github.com/UnlyEd/next-right-now/blob/e5aba8eaf02918d9506008ee1f11c38954fedc86/.storybook/preview.js).

## Writing actual component Stories

Once we were done with the configuration part (around 2.5 days in total), it was time to do the actual work: **Write stories for ALL our components**.

And... it was hard. We had written a few stories during the configuration (of course!) and we knew the basics, but it wasn't obvious what were the "Best practices" really. Also, looking at stuff on the web didn't help and was quite confusing, as they were plenty of examples using v4 or v5, and not many using v6 (which is still quite new!).

At some point, we figured how we'd write our components in such a way we'd avoid code duplication (within stories). But it took us much longer than we wished to.

> To be honest, we don't really know if our way is "the" way. It's one that makes sense, avoids code duplication, is simple to maintain and extend. 
> 
> Is it good? *Definitely*. 
> It is the best? **You tell me**.

Eventually, we managed to write stories for all our components. It took us about 2.5 days.

# Caveats and pains

- Babel/Webpack are real pains. They're like a double edge sword, either you figure out how to configure stuff or you don't. If you do, great, you can now work on the real stuff. If you don't, well, _you suck_. Or that's actually what _it feels like_. Personally, I hate configuring Babel/Webpack, because I'm not familiar with them, and I don't want to learn them either. They're too complicated for my taste, and they evolve with breaking changes too often, too. I don't know why it was so complicated, it just was, and it could have been avoided.
- Storybook documentation is good, but it's not great yet. We got lost several times about how to write our components, met a few bugs that made us feel dumb (_hello `.storybook/manager.js` with your broken cache_), had to go around and around the documentation to find how to configure default stories, override stories, how to disable controls for properties (we eventually wrote [a `withPropMock` HOC](https://github.com/UnlyEd/next-right-now/blob/e5aba8eaf0/src/stories/shared/hocs/withPropMock.tsx to simplify the usage of `children` through a mock prop) for this). TS helps a ton, but there are yet quite a bit of uncovered documentation. They're [working on it](https://github.com/storybookjs/storybook/issues/13499), and we've seen far worse. Overall, we had a good experience, but it can improve!
- Some stuff that should be simple (like sharing CSS for all stories) was quite complicated and really not developer-friendly.
- We ended up re-writing our stories completely several times, until we found the "right" way.

# Final words

Adding Storybook was exciting, a bit needlessly complicated, but [the result is great](https://nrn-v2-mst-aptd-at-lcz-sty-storybook.vercel.app/). It's going to be tremendously helpful for our Product Owner,  Designers and Developers to collaborate at [Unly](https://github.com/UnlyEd), and the team is very excited to benefit from this update once we'll ship it into our private Next Right Now forks!

Having experienced a bit of Storybook v5 and v6, the v6 provides a much better developer experience, great job to the team, it's lovely to see OSS building such great products!