Storybook
A step-by-step guide for installing and configuring Storybook in RedwoodSDK projects.
What is Storybook?
Storybook is a tool for developing UI components in isolation. It allows us to create and test components without needing to run our full application. It can also be a great way to document our components.
Developing UI in isolation is especially useful if we have a component that relies on network requests or our database — we can mock any dependencies and focus on building the component itself.
This guide covers setup and some basics. For full documentation and some demos, see the Storybook site.
Installing Storybook
Because the RedwoodSDK is based on React and Vite, we can work through the "React & Vite" documentation:
Install Storybook:
npm create storybook@latestyarn create storybook@latestpnpm create storybook@latestbun create storybook@latestSelect what we want to use Storybook for — I selected both Documentation and Testing, though this guide will only cover the documentation part:

It'll say it can't detect the framework. Select React — it'll automatically detect Vite:

Storybook will finish installing, and then start our Storybook server:

It should automatically open our browser to Storybook, and if it doesn't, we can go to localhost:6006 to see it:

It also added storybook and storybook-build scripts to our package.json file. We can always run the storybook script to start the Storybook server, and storybook-build script to build our Storybook site for production:
{
"scripts": {
"storybook": "storybook dev -p 6006",
"storybook-build": "storybook build"
}
}Wait, Storybook is showing me some random components!
Storybook comes with some boilerplate components and stories. We can delete the src/stories folder to get rid of them.
Still, if you're new to Storybook, I recommend keeping them around for a bit and taking a look at the files it added. They demonstrate how to set up a Storybook component and how to use and customize the Storybook UI.
Adding a Component to Storybook
In writing this guide, we've started by following the quick start instructions and set up the starter project.
The starter project comes with a very basic Home component:
import { RequestInfo } from "rwsdk/worker";
export function Home({ ctx }: RequestInfo) {
return (
<div>
<p>
{ctx.user?.username
? `You are logged in as user ${ctx.user.username}`
: "You are not logged in"}
</p>
</div>
);
}Given that this is very basic, we'd most likely want to build this out a bit more. Storybook is the perfect place to do that! Let's see what that looks like.
Create a new file: src/app/pages/Home.stories.tsx
import type { Meta, StoryObj } from "@storybook/react";
import { Home } from "./Home";
const meta: Meta<typeof Home> = {
component: Home,
};
export default meta;
type Story = StoryObj<typeof Home>;
export const NotLoggedIn: Story = {
args: {
ctx: {
user: null,
session: null,
},
},
};What is `args`?
args is how we tell Storybook what props to pass to our component. We can think of it as the "input" to our component.
In this case, we're passing the ctx prop to the Home component. As always, if we don't give a component its required props, it'll complain about it.
Save, and go back to our Storybook site. We should see a new "Home" section in the sidebar:

Great! What if we want to mock the logged in user? We can do that by adding a new story, this time passing in a user object to the ctx prop:
import type { Meta, StoryObj } from "@storybook/react";
import { Home } from "./Home";
const meta: Meta<typeof Home> = {
component: Home,
};
export default meta;
type Story = StoryObj<typeof Home>;
export const NotLoggedIn: Story = {
args: {
ctx: {
user: null,
session: null,
},
},
};
export const LoggedIn: Story = {
args: {
ctx: {
user: {
id: "1",
username: "redwood_fan_123",
createdAt: new Date(),
},
session: null,
},
},
};Save it, and go back to our Storybook site. We should see a new "Logged In" story:

What even is a story?
Given that the tool we're using is called "Storybook," it makes sense that it's made up of "stories."
A story captures a single state of a component. It can be thought of as a "use case" for the component.
For example, in our case, we have two stories: "Not Logged In" and "Logged In." Each story shows a different state of the Home component.
We can have as many stories as we want for a component. In fact, it's recommended to have a story for each state of the component.
As we continue building a component, checking back on its stories is also a great way to make sure that we haven't broken anything.
Read more about this in the official Getting Started documentation.
Great! But what if we want to be able to play around with the username that's displayed? Sure, we can always click into the
generated controls and change the username, but it's a little ugly. What if we want to just have a dropdown with some options?
Thankfully, Storybook lets us override the generated controls via argTypes!
Username is nested in our ctx prop, and Storybook controls are meant to correspond with a given prop, so we need to create an array
of all the ctx possibilities we want to test out. We can then give them each a pretty name, and Storybook will generate a dropdown for us —
if we specify a list of options, Storybook will know to use a dropdown control.
Let's do it: