Storybook Flows: specialization of playwright-harness
Read playwright-harness first. This skill contains no Playwright
instruction and never will: all browser execution, screenshots, waits, and
assertions belong to playwright-harness. When a flow's evidence needs to land
on a PR, that is prove-work-on-github; when a captured image needs shrinking,
that is asset-optimization. This skill points to those seams and documents
exactly one thing: how to record human/machine shared steps for running a
flow.
Status: being authored. Definitions, step properties, the visualization spec, and the storage convention are locked; the authoring and reproduction loops are still being dictated and validated. Nothing in here is project-specific: the target Storybook is always parameterized (
STORYBOOK_URL), and flow locations are conventions, not paths into any one repo.
What a flow is
A flow is a sequence of steps that a human or an agent can take inside an application to demonstrate a specific feature.
The same document serves both readers. A human reads it as a walkthrough; an agent reads it as an executable rubric and reproduces it later on its own. If either reader would need a second document, the flow is miswritten.
Flows earn their keep in two situations:
- Issue reproduction. An issue arrives whose reproduction requires a series of steps; the flow illustrates and preserves those steps.
- Integration testing. A series of steps worth testing repeatedly is encapsulated as a flow, and an agent drives it.
Self-containment (the transportability rule)
Flows do not reference other flows. Every flow is internally consistent, internally self-contained, and therefore transportable.
During authorship it is fine for a flow to be described in terms of another flow ("log in, then..."); the referenced steps are then inlined into the new flow. If a detailed authentication flow exists and a new flow begins with "log in", the authentication steps are copied into the new flow, not linked. Assume the person or agent executing a flow has no knowledge of any other flow.
The single exception is a precondition (below): required starting state may name another flow; steps never do.
Preconditions (required starting state)
A flow may require a certain state to have already taken place before step 1, in the manner of a Cucumber scenario outline: "if you are already logged in, then perform the flow."
In this context only, a flow may reference another flow as the way to reach the required state. The precondition names the state and the flow that establishes it; it is not a step, and it is not inlined. Steps inside the flow body still never reference other flows.
The final state
Every flow ends in success or failure, and every flow must define its final success state. Completing all steps in sequence, including the last one, with no problems and no errors thrown, is success. Without a defined success state neither an integration test nor a QA tester can know the flow completed; with one, the flow is a pass/fail instrument.
Steps
A flow consists of steps. A step is complete only when it has all of the following properties:
- A number. Steps are numbered and execute in sequence.
- A title. Short and succinct: "Log in", "Click button".
- A description. A short account of the action being taken.
- A route. The route the step takes place on, as a clickable link (described below).
- A visualization. The most important property, described below.
Routes and the base URL
Flows take place inside a web application, so every flow is on some route, and the flow records it. The route appears at the flow level as well, beyond the scenario outline, not only on individual steps.
Routes are recorded as clickable links, and they resolve against a configured base:
- A configuration sits at the root of the flows folder and declares the default base URL for flows, pointing at the QA server or the development server. There must be a default test root URL for flows.
- Routes in flow documents are authored relative to that base. If the
configuration says the default flow base is
www.my-qa-server.com/testers, every route described while authoring is relative to it, and the rendered links point into that server. - Runners substitute the base. When an agent runs a flow locally, it replaces the base URL and drives the same relative routes against the local server.
- A flow may override the base. If a flow is authored against a specific environment (reproducing something that happens in production, say), the author states that during authoring; the override is written into the flow document itself and all of its clickable links resolve against the override instead of the default.
The visualization
A visualization is, ideally, an actual inline component: the real component rendered in the flow document, not a description of it. Flows are MDX files in Storybook, so inlining the real thing is cheap; do it.
How a narrated step becomes a complete one. The narrator says "go click the login button", and that is everything a step needs:
- Title: "Click login".
- Description: where the login button is located on the page.
- Visualization: literally inline the component, based on the actual code cross-referenced with the component itself. Look the button up in Storybook, look at its source code, and put that button (and, where it helps, its surrounding context) inline as the visualization.
The visualization carries the same accessibility tags an agent would see when actually driving the page. That is the point of it: a human sees a button that looks exactly like the button on the page; an agent sees the accessibility hint that locates it quickly. Flows are therefore highly accessible by default; a visualization without the real accessibility surface is incomplete.
Present agent-facing detail as secondary content. The human walkthrough reads clean without it: the accessibility surface renders collapsed (a disclosure the human can expand), while an agent — which reads the document, not the folds — always sees it. Both readers get what they need from the same page.
Fallback. When a component cannot be inlined, take a screenshot of the
region of the page the step describes and inject that screenshot into the MDX
file. Capture per playwright-harness; shrink per asset-optimization before
it is committed.
Where flows live
Inside the project, prefer a /docs folder, unless the author has overridden
their default root-level Storybook documentation folder; in that case, use
theirs. Inside it:
- a
/flowsfolder (author it if it does not exist); - every flow gets its own folder, named after the user story it depicts;
- the flow's point of entry is its
index.mdx; - artifacts live beside
index.mdxin the flow's folder: images, gifs, and special components (for example, a component depicting two components side by side that would not normally be side by side).
docs/
└── flows/
└── <user-story-name>/
├── index.mdx <- the flow; root point of entry
└── <artifacts> <- images, gifs, special components
In the Storybook sidebar, the flow's Meta registers under a root-level
Flows folder, then the name of the flow:
<Meta title="Flows/<Flow Name>" />.
Authoring a flow (the interactive loop)
Authoring is an interactive process: a human dictates, and every discrete instruction becomes a step inside the flow.
- The developer says "do this."
- You do it (drive it per
playwright-harness). - You immediately write down what you did, as a step with all of its properties (number, title, description, route, visualization) — before taking the next instruction.
- Repeat until the developer tells you that reaching this point is success.
The rhythm is strict and per-step: follow the instruction, write down the step; follow the instruction, write down the step. Every successfully completed action is recorded in the flow document the moment it is confirmed — steps are never batched up to be written later. If the flow document does not yet show a step you have driven, you are behind; write it before anything else.
That declaration is the flow's success criteria; encode it as the flow's final success state. A step that was never driven does not get written down, and nothing gets written down that was not dictated.
Flows are direct. Branching conditions are not supported. If a dictated sequence wants to branch, that is two flows.
Insufficient accessibility is fixed at the source, during authoring. If a
dictated step's target element cannot be located by its accessibility surface
(no role, no accessible name), do not settle for locating it by geometry or
styling: open the component's source, decorate the element (accessible role
and name — aria-label, accessibilityLabel, or the platform equivalent),
and update the codebase with that change as part of the authoring session. The
step's visualization then carries the element's real accessibility surface, as
required. Authoring is when these gaps surface, and fixing them serves a dual
purpose: the page becomes discoverable by humans, agents, and
assistive-technology users alike.
Reproducing a flow (run by name)
The second mode: someone tells the agent to test a feature by running a flow on its own, and they name the flow. The agent:
- finds the named flow in the flows folder (its own folder under
/flows, entered atindex.mdx); - executes the steps in order, translating each step's description and
visualization (including its accessibility hints) into
playwright-harnessdriving; - gates on the flow's final success state: all steps completed in sequence, including the last, with no problems and no errors thrown, is success; anything else is failure.
Divergence between the flow page and reality is a finding to report, not something to silently patch around.
Both modes are required. An agent using this skill must be able to author interactively and to reproduce by name.