Versapay moves money for finance teams. Two years of it ran through our hands: the platform's move off Ruby onto React, the design system that made that move survivable, and the reporting product that shipped on top of it.
RECONSTRUCTED FROM THE PRODUCTION FIGMA FILE · SCROLL SIDEWAYS ON A NARROW SCREEN
Figures published by Versapay. They matter here for one reason: at that volume a design decision is never small. A button that reads wrong becomes a support queue.
A legacy Ruby product had grown into something no one could describe in a single sentence. Every team had its own version of a table, a date picker, a warning. The engineering plan was React. The design problem was that nobody had written the language down.
Finance teams work inside these screens every day and month end does not pause for a redesign. Nothing could be relearned.
If a component could not be built exactly as drawn, it was the drawing that was wrong. Variants were specified to match props, not to look tidy in Figma.
Canned Reports became the first product built entirely on the new system. If the system worked, this shipped clean.
Structure argued out in grey boxes, where changing your mind is free.
Directions kept on their own page so bad ones stayed visible and reviewable.
One question tested properly: navbar or dropdown for report selection.
Every state of the shipped feature, including the ones nobody likes drawing.
Both reports visible at once. Testers understood there were two products without opening anything, and switching cost one click instead of three.
Tidier at rest and worse in use. It hid the fact that a second report existed, and people asked for a feature that was already there.
Generation is asynchronous, so the design's real job was waiting. We treated the wait as a state with its own screen, its own copy and its own exit, instead of a spinner and hope.
Report type, then a date range. Two decisions, no configuration screen.
A four step load animation and a row you can leave. Closing the tab does not cancel the job.
The notification is the product. The .CSV sits in the table until it expires.
An empty report is not an error. It says what was searched and offers a wider range.
Customer adoption and payment adoption answer different questions but behave identically. Same table, same picker, same download. Learning one taught you the other.
Every axis in the library maps to a prop. Size, colour, state, variant. A developer never had to guess which of four almost identical buttons was the real one, because there was one button with 297 legal combinations.
Once the language existed, screens could be rebuilt in React without a fresh design debate each time. Reporting shipped on the new system and became the reference other teams copied from.
Two years of enterprise work leaves a specific habit behind, and it is the reason this studio exists: draw the boring states, write the numbers down, and hand engineering something they can build without calling you.
Components specified against React props so design and code stayed in step.
Structure and vocabulary preserved through the rebuild, so nothing had to be relearned at month end.
Navigation settled by a user test, not by whoever spoke last in the review.
Canned Reports went out as the first product built entirely on the new system.
Versapay is the client. All product names and trademarks belong to Versapay. Screens here are reconstructions built for this case study, shown to describe the design work rather than to represent current production software.