# Tiny Alternative to Storybook

import { Shortcut } from "../src/lib/Shortcut";

<Callout>

TLDR: Using a set of documentation components rendered inside of your app on
_/docs_ page may be an interesting alternative for Storybook.

[See my documentation components on CodeSandbox.][sandbox]

</Callout>

[sandbox]:
  https://codesandbox.io/s/documentation-components-example-dm1vl?file=/pages/index.tsx

## The Problem

The main problem I have with Storybook is that it's _another set of config files
to maintain_. What's worse — there's a Webpack config hidden inside! Ouch.

Don't get me wrong! I quite like Storybook, and I use it for any professional
design system I work on, but I'd put it in "tooling that sometimes breaks and
needs to be maintained" category. It's a huge tool. It has tons of awesome
features — a huge surface, a multiplicity of choices.

But do you really need it when you're trying to launch an app?

## Storybook and Libraries

Where Storybook shines the brightest is libraries. You can presume that most
frontend folk are familiar with Storybook or will be able to pick it up fast.
It's so popular we could probably call it a standard for component examples.

It's as easy to contribute a story as it is to write a piece of markdown for the
docs. Thanks to its popularity, Storybook lowers the burden put on library
maintainers.

## Alternative Approach

However, you can do without Storybook! I've found myself reaching for a smaller
alternative in new projects.

Here's the gist — We can classify Storybook as _documentation catalogue_ or
_components atelier_ software. Such a thing has a few main parts:

1. File-system router which grabs your files and turns them into pages
2. UI to render examples
3. Development server which refreshes your examples when you change the code
4. Some search functionality for navigation

Let's address search — If I'm early enough in the project to be worried about
Storybook config maintenance cost slowing me down, I probably don't have enough
components to warrant search anyway. <Shortcut shortcut="cmd+f" /> will be
enough.

Thing is, in most cases I already have file-system routing and a nice dev-server
with React Fast Refresh support. I don't need to maintain another webpack config
to give me the same experience I already have while developing my app.

<details>
<summary>
  Historical Context: In the past Storybook was awesome, because the ecosystem was worse.
</summary>

A lifetime ago, I used to work on a sizeable legacy codebase and wait for 4
seconds or more for the app to reload. Then I had to and reproduce the state I
was in if it wasn't possible to hardcode it. — Storybook's stories solve this
problem elegantly.

Until we eventually migrated from [Brunch](https://brunch.io/) to Webpack and
configured `react-hot-loader`, Storybook was my safe haven for UI-focused tasks,
and thanks to it a migration from jQuery to React went like a breeze.

Months later, when our SPA grew even more, and Flow compilation times got slow,
Storybook was a huge help in onboarding new engineers in the team and getting
them started quickly.

</details>

In 2021, thanks to wide-spread file-system routing and fast development servers,
we can easily create a `/docs` page or a few of them.

So we're down to _"UI to render examples"_.

I've created a [CodeSandbox][sandbox] with some of React components I'm using for docs in one
of my projects. Here's how they look like in the editor:

```tsx
import { ComponentExample, ComponentExamplesContainer } from "./docs-ui";
import { Text, Link, Button } from "./actual-app-ui";

const Examples = () => (
  <ComponentExamplesContainer>
    <ComponentExample>
      <Link href="https://example.com">example.com</Link>
    </ComponentExample>

    <ComponentExample>
      <Button variant="primary">Start Game</Button>
      <Button>Exit</Button>
      <Button size="large">Click Me</Button>
    </ComponentExample>
  </ComponentExamplesContainer>
);
```

And here's how they render in the browser:

[![Scrolling through UI examples page](https://i.gyazo.com/a5750ce4db513d66d5ba483faa0b5437.gif)][sandbox]

By focusing on documentation UI and forgetting about routing, search and
dev-servers, we reduced complexity enough that copying these components between
projects and maintaining them when any change is needed isn't a burden.

## Trade-Offs

Obviously, this idea has trade-offs that we need to consider.

- Storybook supports 12 component frameworks, but I just need one at a time.
- I lose access to a huge plugin ecosystem, but I want to go _smaller_ and
  remove everything we don't desperately need.
- And the most serious problem — I will definitely not handle all corner cases
  at first, so I'll need to revisit the code and expand it as I use it. We're
  not free from maintenance. Question is — Is maintaining a set of
  _programmable_ components in your language/framework of choice easier than
  maintaining a bunch of config files?
- My components work at _runtime_ and reconstruct the source code for the
  example based on its React elements tree. Our code is most often transpiled,
  so what we see in component examples may not be the same thing we wrote. While
  sufficient for simple cases, this approach is problematic for more complex
  constructs. If you're documenting a public library, not just reusable
  components from an app, a build-time solution like Storybook or an
  [MDX/rehype-based solution](https://ped.ro/blog/code-blocks-but-better) will
  definitely be a better choice.

## Notes

### Write or Install

I'm intentionally not publishing these components as a library, even for my use,
because I wrote them explicitly not to use a library. Maintaining a familiar
code in your repo may often be easier and less time-consuming than using a
ready-made tool. _Programmable_ APIs are more robust than _Configurable_ APIs.
"Write or Install" is a variation on "Build or Buy" dilemma we don't talk about
enough.

---

<figure>

> I have never seen new startups get any value from Storybook. It only slows
> them down.
>
> I can totally see the value for enterprise and established startups. But when
> running out of time &amp; money, the #1 focus is getting launched!
>
> Launched &gt;&gt;&gt; beautiful storybook but no customers

<figcaption>

[—Brandon Bayer, July 24, 2020]("https://twitter.com/flybayer/status/1286556994829074434?ref_src=twsrc%5Etfw")

</figcaption>
</figure>
