Evidence-Based Design

Experience-Based Decomposition

The most common complaint about user interfaces in long-lived products is not that individual screens are poorly designed. It is that changing anything requires touching everything.


The Problem

Frontend frameworks present an implicit model: routes map to pages, pages contain components, components contain logic. This works when an interface is small and stable. It breaks down as the product matures. State that belongs to a multi-step sequence ends up in a parent component. Navigation decisions get duplicated across components. Business logic migrates into presentation components because there is no structural location for it.

The root cause: code is organized around screens, but users are organized around purposes.

A user opening a developer onboarding tool is not navigating to a screen. They are pursuing a goal — getting their environment configured correctly — and that goal may involve seven screens, four API calls, three conditional branches depending on their organization’s configuration, and a different set of form fields than their colleague. None of that variation lives in the goal itself. The goal is stable. The implementation of it is what varies.

The Core Idea

EBD establishes human intent as the organizing principle of interface structure. Structure follows intent. What varies is isolated from what endures. The principles are the same ones that underpin VBD at the system level — applied here to the surface that users actually touch.

The Four Axes of Interface Volatility

Before defining the structural model, EBD characterizes where change actually occurs in interface systems — the same volatility analysis that underpins VBD at the system level.

AxisWhat ChangesContaining Tier
FunctionalNew fields, validation rules, options, stepsInteraction
StructuralNew audience paths, conditional sub-journeys, entry pointsExperience
Cross-CuttingLocale, theme, validation conventions, error formatUtility
EnvironmentalBackend API shapes, authentication, configuration schemaAPI Accessor

The Three Tiers

Experiences

A complete user journey bounded by a human intent — the arc from initiation to fulfillment. What did this user come here to accomplish? Experiences are the most durable tier. The intent behind a developer onboarding experience endures across product iterations, new configuration types, and new platform targets. An Experience should be reconsidered only when the underlying human purpose changes, which is rare.

  • Own the composition of Flows that constitute the journey
  • Hold the complete state accumulated across all Flows
  • Are the only tier that communicates with the backend — because only the Experience has the full picture across all Flows
  • May receive configuration that determines which Flows execute and in what order
  • May compose other Experiences as bounded sub-journeys
  • Must not implement flow-level progression logic or render Interactions directly

Flows

A goal-directed sequence of Interactions that accomplishes one discrete outcome. One Flow, one purpose. Flows sit at the most structurally important tier — the one most commonly absent from interface codebases. Because they have no natural representation in screen-first frameworks, flow logic ends up distributed: navigation conditionals in parent components, validation in leaf components, accumulated state in global stores. When the Flow has no home, everything becomes its home.

  • Own progression through Interactions and accumulated state
  • Do not communicate with the backend — that is the Experience’s concern
  • Must not coordinate directly with sibling Flows
  • Emit completion events carrying accumulated state upward to the Experience
  • May skip entirely if entry conditions are not met, signaling the Experience to advance

Interactions

The smallest observable unit of user action — atomic and indivisible from the user’s perspective. A selection, an input, a confirmation, a toggle. Interactions are the surface — what users actually touch.

  • Render a single input surface, accept user input, emit events
  • Carry no flow logic, make no API calls
  • Have no awareness of adjacent Interactions
  • Are the most reusable and the most frequently changing tier

Communication Rules

Configuration drives the Experience, which passes shared state downward to Flows. Flows pass props and callbacks to Interactions. Interactions emit atomic events upward. Flows emit completion events upward to the Experience. The Experience holds accumulated journey state and is the only tier that communicates outward.

The prohibited patterns mirror VBD exactly: no peer coordination (Flows do not call sibling Flows), no boundary-skipping (Interactions do not consume other Interactions), no external calls below orchestration (Flows do not call the backend API). It is the coordination between tiers that captures volatility, not individual tiers in isolation.

Relationship to Component Libraries

A component library answers the question: how do we build consistent interface elements? It does not answer: where does navigation logic live? Who owns multi-step state? What happens when a step should be skipped? Those questions require a structural model, not a component model. EBD provides the structural model. Component libraries and design systems provide the visual vocabulary. Both are necessary; neither replaces the other.

Configuration-Driven Composition

When the EBD structure is in place and backed by an event-driven communication model, Experiences can be defined and composed through configuration rather than code. An organizational configuration, a feature flag, an audience-specific ruleset — any of these can alter what an Experience contains, in what order Flows execute, and how the backend responds to their completion events. The interface becomes programmable at the intent level, not just the component level.

Where EBD Applies

EBD applies most directly to long-lived products, systems serving multiple audience types with distinct mental models, and any product that must remain coherent across years of continuous evolution. It extends the goal-directed design tradition — originally articulated by Alan Cooper — from the specification level into the codebase structure, ensuring that the organizing principle persists into implementation rather than dissipating when coding begins.