Building a Next.js app using Tailwind and Storybook
Tags: nextjs, webdev
Published: 2023-03-07 18:34:17

**Written by [Elijah Asaolu](https://blog.logrocket.com/author/asaoluelijah/)✏️**

Component-driven development has transformed how we create web applications. This development approach makes it easier to manage and maintain application codebases while also facilitating design consistency and collaboration among developers. 

One of the primary advantages of component-driven development is component isolation, which allows you to work on components independently without being distracted by the surrounding application. Storybook.js is one tool that can help with this. 

In this tutorial, we'll go over what Storybook is, how it works, and how to get started with creating stories in a Next.js application [using Tailwind CSS for styling](https://blog.logrocket.com/using-tailwind-css-in-production/). We will cover:

*   [What is Storybook?](#what-storybook)
*   [Getting started with Next.js, Storybook, and Tailwind](#getting-started-next-js-storybook-tailwind)
    *   [Adding Storybook to a Next.js app](#adding-storybook-next-js-app)
    *   [Adding Tailwind CSS support for Storybook](#adding-tailwind-css-support-storybook)
*   [Creating stories for our Next.js and Tailwind project](#creating-stories-next-js-tailwind-project)

To follow along with this tutorial, you must be familiar with Next.js and Tailwind CSS. Previous experience with Storybook may also be beneficial; however, this article will attempt to cover the basics quickly.

## What is Storybook? <a name="what-storybook">

Storybook is a web tool for developing and testing UI components in isolation from a specific application. It allows you to create "stories" for each component, which are examples of how the component should look and behave in different contexts: ![Example Button Component Created In Storybook With Preview Of Blue Rounded Button At Top Of Display, List Of Various Components In Left Menu Bar, And Controls For Button Component Encompassing Bottom Half Of Image](https://blog.logrocket.com/wp-content/uploads/2023/02/img1-Example-Storybook-button-component-settings.png) 

The stories you create can then be displayed in a browser in a development environment, allowing you to easily test and debug your components. 

Storybook includes several useful features, such as the ability to add notes, control the component's state, and check accessibility rules. 

It also allows you to interact with the component props and preview how the component would look in different scenarios and states, which in turn allows you to test and debug effectively.

## Getting started with Next.js, Storybook, and Tailwind <a name="getting-started-next-js-storybook-tailwind">

Let's get started with creating a new Next.js application by running the command below:

```bash
npx create-next-app next-storybook
```

Next, change directory (`cd`) to the new app, then run the following command to install Tailwind CSS and its dependencies:

```bash
npm install -D tailwindcss postcss autoprefixer
```

After this, run the command below to generate both `tailwind.config.js` and `postcss.config.js` as required by Tailwind CSS:

```bash
npx tailwindcss init -p
```

Open the `tailwind.config.js` and update its code to the one below, so that the content export includes files in our project’s `/pages` and `/components` directories.

```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./pages/**/*.{js,ts,jsx,tsx}",
    "./components/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
};
```

Finally, open the default `styles/global.css` file and add the `@tailwind` directives shown below to the top of the code:

```css
@tailwind base;
@tailwind components;
@tailwind utilities;
```

At this point, we've successfully configured our Next.js app to work with Tailwind CSS and can begin utilizing Tailwind's utility classes.

### Adding Storybook to a Next.js app <a name="adding-storybook-next-js-app">

You can add Storybook to a Next.js application simply by running the following command:

```bash
npx sb init
```

If you’re using Next.js v11 and later, it is recommended to [use webpack 5](https://blog.logrocket.com/new-features-in-webpack-5-2559755adf5e/) for improved integration and performance:

```bash
npx sb init --builder webpack5
```

Running any of these commands will install the required dependencies and set up a storybook environment for your project. There should also be two new folders created — `.storybook` and `stories`. 

The `.storybook` directory contains a `main.js` file and a `preview.js` file. These let us configure the look and feel of our application, as well as allowing us to engineer our Storybook environment to our preferences. 

The `stories` folder contains default stories and documentation. We'll learn how to create our own in a moment. 

To test things out, use the following command to launch the Storybook interface:

```bash
npm run storybook
# OR 
yarn storybook
```

A new webpage should open at `http://localhost:6006`, and you should see something like this: ![Example Storybook Interface For How A Page Component Would Appear In The Frontend For A Logged Out User](https://blog.logrocket.com/wp-content/uploads/2023/02/img2-Example-Storybook-interface-page-component.png) 

Play around this environment to get a better understanding of how stories and documentations work in Storybook before we begin creating our own. 

Once you’re done playing around, go ahead and delete the `/stories` directory, then update the content of `.storybook/main.js` to match the following:

```javascript
module.exports = {
  stories: [
    "../components/**/*.stories.mdx",
    "../components/**/*.stories.@(js|jsx|ts|tsx)",
  ],
  addons: [
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    "@storybook/addon-controls",
  ],
  webpackFinal: async (config) => {
    config.module.rules.push({
      test: /\.scss$/,
      use: ["style-loader", "css-loader", "postcss-loader", "sass-loader"],
    });

    return config;
  },
};
```

In the code above, we configured Storybook to look for stories/documentation in the `/components` directory rather than the default `/stories` directory, allowing us to house our components as well as their respective stories in the same directory.

### Adding Tailwind CSS support for Storybook <a name="adding-tailwind-css-support-storybook">

Storybook does not work with Tailwind CSS by default. As a result, if we [create a React component using Tailwind](https://blog.logrocket.com/using-storybook-to-develop-react-components-faster/) utility classes and then create a story based on this component, the Tailwind CSS changes will not be reflected in the Storybook environment. 

To address this issue, we’ve added a `webpackFinal` option to the `.storybook/main.js` config file in the previous code. This will instruct Storybook to build with the necessary dependencies required by Tailwind CSS:

```javascript
. . .
  webpackFinal: async (config) => {
    config.module.rules.push({
      test: /\.scss$/,
      use: ["style-loader", "css-loader", "postcss-loader", "sass-loader"],
    });

    return config;
  },
```

Also, update the `.stories/preview.js` file with the code below:

```javascript
import "../styles/globals.css";

import * as nextImage from "next/image";

Object.defineProperty(nextImage, "default", {
  configurable: true,
  value: (props) => <img {...props} />,
});

export const parameters = {
  actions: { argTypesRegex: "^on[A-Z].*" },
};
```

This file was updated to import the global stylesheet and to support `next-image`. As a result, both Tailwind CSS and `next-image` should function properly in our Storybook environment.

## Creating stories for our Next.js and Tailwind project <a name="creating-stories-next-js-tailwind-project">

To create a new story, we need to first create the component on which the story will be based. Create a new `/components/Card` folder in your project root directory. Then, inside this new directory, create two files:

*   `index.js` — will contain the main code for our card component
*   `card.stories.js` — will contain the story code for our card component

When we're finished, our project file structure should look like this:

```javascript
.
├── . . .
├── components
│   └── Card
│       ├── index.js
│       └── card.stories.js
├── pages
│   └── index.js
├── public
└── . . .
```

Inside the `Card/index.js` file, paste the following code:

```javascript
import PropTypes from "prop-types";

const Card = ({ title, showSub, background, imgUrl, children }) => {
  return (
    <div class="flex justify-center">
      <div
        class={`flex flex-col md:flex-row md:max-w-xl rounded-lg bg-${background} shadow-lg`}
      >
        <img
          class=" w-full h-96 md:h-auto object-cover md:w-48 rounded-t-lg md:rounded-none md:rounded-l-lg"
          src={imgUrl}
        />
        <div class="p-6 flex flex-col justify-center">
          <h5 class="text-gray-900 text-xl font-medium mb-2">{title}</h5>
          {showSub && (
            <p class="text-gray-500 text-sm mt-2">This is the card subtitle</p>
          )}
          <p class="text-gray-700 text-base mt-4 mb-4">{children}</p>

          <button
            type="button"
            class="inline-block px-6 py-2.5 bg-blue-600 text-white font-medium text-xs uppercase rounded shadow-md"
          >
            Some action
          </button>
        </div>
      </div>
    </div>
  );
};

export default Card;

Card.propTypes = {
  title: PropTypes.string,
  sub: PropTypes.string,
  showSub: PropTypes.bool,
  imgUrl: PropTypes.string,
  background: PropTypes.string,
};
```

Using Tailwind CSS utility classes, we created a component in the code above that accepts `title`, `showSub`, `imgUrl`, `background`, and `children` prop and generates a basic card with the passed props. 

You may have noticed that we also used [the React `PropTypes` package](https://blog.logrocket.com/validate-react-props-proptypes/) to define our prop types. We'll need to install it like so:

```bash
npm install prop-types
```

To create the card story, paste the following code inside the `card.stories.js` file:

```javascript
import Card from "./index";

export default {
  title: "My Cards",
};

const Template = (arguments_) => <Card {...arguments_} />;

export const GreenCard = Template.bind({});

GreenCard.args = {
  title: "Hello World",
  showSub: false,
  background: "yellow-600",
  imgUrl: "https://path/to/some/image",
  Children: "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nulla, soluta?",
};
```

In the code above, we created a new story called "My Cards," binding the story template to the `Card` component we created earlier. 

We then created a new instance of the `Card` story called `GreenCard` and passed the above `GreenCard.args` values as props to be rendered with our `Card` component. 

Run the following command to restart the Storybook environment:

```bash
npm run storybook
```

Once it's started, you should see that our card story is now created as shown in the screenshot below: ![Example Card Component Created In Storybook With Controls Displayed For Card Elements Like Title, Background Color, Image Url, And Children](https://blog.logrocket.com/wp-content/uploads/2023/02/img3-Example-created-card-story-Storybook.png) 

You should also notice that our component is automatically updating as we make changes in the control section. 

Furthermore, we have a plethora of customization options at the menu bar for measuring the sizes of our component as well as how it will appear in various viewports and conditions: ![Storybook Card Component Preview With Red Boxes Indicating Where Customization Options And Other Controls Can Be Found And Edited](https://blog.logrocket.com/wp-content/uploads/2023/02/img4-Storybook-card-preview-customization-options-menu-bar-other-controls.png) 

That's all there is to it! We were able to install Storybook in a Next.js project and set it up to work with Tailwind CSS.

## Conclusion

Throughout this article, we have emphasized the importance of component isolation. We also discussed how to use Storybook — a web tool for developing and testing UI components in isolation — in a Next.js application, as well as how to configure Tailwind CSS for such a project. 

You may also find the complete [source code for this tutorial on GitHub](https://github.com/AsaoluElijah/next-tailwind-storybook).

---

## [LogRocket](https://logrocket.com/signup): Full visibility into production Next.js apps

Debugging Next applications can be difficult, especially when users experience issues that are hard to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try [LogRocket](https://logrocket.com/signup). 

[![LogRocket signup](https://blog.logrocket.com/wp-content/uploads/2017/03/1d0cd-1s_rmyo6nbrasp-xtvbaxfg.png)](https://logrocket.com/signup)

[LogRocket](https://logrocket.com/signup) is like a DVR for web and mobile apps, recording literally everything that happens on your Next app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your Next.js apps — [start monitoring for free](https://logrocket.com/signup).