How Aesop Happened

keithrcagney
Aesop-Storybook
Published in
5 min readJan 16, 2020

Some of the best lessons learned in software engineering occur at the crossroads between design ambitions and happy accidents.

This is a story about five guys who found that out. Repeatedly.

Best-Laid Plans

Kenny laying out the roadmap.

When our team set out to write a Visual Studio Code extension for Storybook, we had big things in mind. We love Storybook. We love the community support it receives, the constant addition of addons and “I didn’t even know I needed that before now” features, and its clean, dev-friendly UX.

The one thing we weren’t in love with, as we discovered over coffee, was the hiccup in our workflow when swapping out of VS Code to view stories in the browser. So we started a repo for Aesop.

The trick was to preserve core capabilities that devs rely on, while ensuring Aesop played nice with of Storybook’s supported visual component libraries. We wanted to bring Storybook in tighter sync with a visual testing workflow, eschew the browser altogether, and let you see the results of HMR right beside your codebase.

By the time the check came, we had a stack in mind, a way forward with Websockets, and a whipped-up Node server to snag what we needed from Storybook.

But we were way off-mark.

Deep-diving with Storybook

Once we had pulled down Storybook’s repo and begun testing, we gnawed on the first blocks. Where the heck was the Webpack configuration file?

Turns out Storybook’s Webpack implementation bundles using a configuration object generated as a series of function outputs. Though we found points of egress to assert properties on that config, there wasn’t an intuitive way to do it without breaking the Storybook startup sequence in some way.

On the other end, we learned that the Visual Studio Code extension API is purposefully limited in a few key ways. To maintain the integrity of the user’s workspace, files, and file system, extension builders need to be more explicit about permissions than we’d known, and much more stringent with type assertions. This meant that our options were slim when considering how best to display content.

Back to the Drawing Board

An early debug screen of Aesop finding a Storybook.

We started out with a simple scale. As most of our team is best-versed with the React library, Aesop was first intended solely for React development.

One of our early feature branches involved mapping Treeview items to the VS Code Explorer to replace Storybook’s UI panel. We even tested a React-like library (we were calling it Fable) to traverse the file system and render components in the preview panel using TextDocumentProviders. The approach was very inspired by the React-Native Storybook extension, but without its Websocket underpinnings (though we tried that, too).

We tangled with the Storybook manager for a non-negligible portion of our initial sprint on nailing that down. Then a recent Storybook update introduced a handy hotkey to hide the UI panel. Press F to pay respects to that branch.

Given those setbacks, we soon realized the best implementation was what Aesop is today: a lightweight, as-silent-as-can-be preview panel. It’s essentially a self-deploying, Node-savvy, minified browser.

WebviewPanels are a type natively defined in the VS Code API, like a logic-backed iframe wrapper, which in turn can be handed an HTML document capable of mirroring localhost content.

With this new course, we got down in the docs and had Storybook content outputting in just a few hours. But we didn’t feel like we’d accomplished much.

The Long Road to Aesop

Aesop, at home with your code.

Yet deciding to be hands-off with the Storybook codebase ended up being the perspective we needed. After the shock of accomplishing a goal too quickly subsided, we saw the next move. We began to think harder about our core design principle of workflow optimization, and it became clear that Aesop should be as minimum config, all-in-one solution as possible. So we got under the hood with Node.

Our team has built plenty of Node servers. But before tackling this project, none of us had gotten so much hands on time with its more robust abilities, especially when it comes to processes, events, and OS-specific arguments.

Aesop became an elegant exercise in edge cases. In its final production build, it took the form of a lively, asynchronous activation function that accomplishes a few things at once.

It first accesses your working directory and looks for an Aesop dependency. Once accomplished, it accommodates those devs who are used to spinning up Storybook from the command line — or who might still want to have a backup browser window to see larger renders — by listening in on Node processes to attune to that port.

If Aesop does not find a Storybook process running, it takes the lead and executes it for you, accessing your package.json file to see if you have passed in a port of your own to work with, and doubles back to make sure Storybook didn’t need to resolve a busy port conflict.

Enter Aesop

In the end, a project born of caffeine and some overtired musings became a crash course in features-testing, assumptions gone wrong, and a redefinition of simplicity. And we’re proud of the little guy.

The Aesop extension is a humble helper for Storybook, with a lot of room to grow. We look forward to adding more features, and we’re thankful for all feedback as this project continues.

You can download Aesop on the Visual Studio Code Marketplace here. Please feel free to reach out to Team Aesop or visit our Github repository to let us know what you think.

--

--