Post-Its Don't Survive a Pandemic

rubyrailsbuilding-in-public

We’ve been doing user story mapping for over a decade. Jeff Patton’s method: activities across the top as the backbone, releases as horizontal lanes, stories placed at the intersection of where they belong in the user journey and when they’ll ship. It’s a fantastic way to see the full shape of a product and spot the gaps.

For most of that decade, story mapping meant post-its on a giant wall. You’d book a room, grab a stack of sticky notes, and spend a few hours arranging and rearranging until the map made sense. We even had a dedicated box with special edition post-it colors, colored dots, stars, arrows, flags and painters tape so we could story map anywhere. It’s still sitting on my shelf and I’m looking at it as I write these lines. Photos of the wall became the documentation. Some stickies would end up as epics in Jira and they’d evolved from there. It was messy but it worked, because everyone was in the same room looking at the same wall.

During COVID-19 that all changed: the post-its were still on the walls, but locked away in an empty office. Neglected but never forgotten.

We tried the obvious workarounds: Miro, online doodle spaces, shared whiteboards. They’re fine for brainstorming but they’re not story mapping tools. There’s no concept of activities and steps forming a backbone. No release lanes. No status tracking on individual stories. You’re just placing rectangles on a canvas and hoping the spatial layout conveys the structure. It sort of works, but you lose the constraints that make story mapping useful. The backbone isn’t enforced, the release boundaries are just lines you drew, and nothing connects back to where the actual work gets tracked.

Even after offices reopened, the post-it wall didn’t recover. Hybrid work means people aren’t always in the same room at the same time. The physical story map stopped being the shared artifact it used to be. Someone would update the wall, someone else would be working from home and not see the change. In the end we sort of gave up.

So I started looking at digital story mapping tools. Avion, StoriesOnBoard, and a few others. They exist, they do story mapping. But they’re SaaS tools that live in their own world. They don’t integrate with our issue tracker, our CI server, or our internal infrastructure, which is now in a state of question mark anyways with Atlassian having announced the end of life for our hosted Jira and Bitbucket by February next year.

On a Journey

We set out to build our own in early October. How hard could it be? Kanban boards and drag and drop were largely solved by now. A story map is nothing but a giant Kanban board with lots of columns and swimlanes!

By the end of the first week we had the core domain: activities, steps, stories, releases, all backed by proper models with drag-and-drop sorting. The story map renders as a grid: columns are steps grouped under activities (the backbone), rows are release lanes, and stories sit at the intersections.

Inline editing everywhere: click a story name, type, press enter. Drag a story to a different step or a different release. Collapse release lanes you don’t need to see right now. The interactions needed to feel as fluid as the physical wall, or people would just go back to post-its.

By week two we had authorization (Pundit), project settings, and story detail cards in modals with full descriptions. Week three brought team features: multiple teams, project memberships with roles, invitations. Week four: story map duplication, context menus, moving maps between projects.

Five weeks from first commit to daily driver.

The data model

A story map is a two-dimensional grid:

Each story has a name, description, estimate, status (via a workflow), and optional label. Workflows are per-map with customizable steps. The default is Not Ready → In Progress → Done, but you can define whatever fits.

Releases have start and due dates, shipped/archived/locked flags, and track completion percentage. The “Unplanned” release is created automatically for stories that haven’t been assigned to a release yet.

The whole thing is scoped: Teams → Projects → Story Maps. A team can have multiple projects, each project can have multiple maps. Roles propagate: a team admin is an admin on all projects in that team.

What it replaces

The physical wall, obviously. But also the transcription step, that manual process of turning post-it notes into Jira tickets. In Journey, the stories on the map are the work items. There’s no separate system to keep in sync.

The export/import feature means story maps are portable. Dump one to JSON, import it into a different project or a different instance. This replaced the “take a photo of the wall” workflow with something that actually preserves the structure.

Where it stands

We’ve been using Journey for real planning for a couple of weeks now and it’s already changed how we work. The map view makes the product shape visible in a way that no flat backlog ever did. Dragging stories between releases during a planning session feels natural. The same fluid rearranging we used to do with post-its, but everyone can see it from wherever they are.

The post-its aren’t coming back.