A $750M-a-year checkout at 9% success, on a backend nobody could touch. I redesigned the flow on top of it, tested six versions on live traffic, and then built the next product with AI from the first wireframe.
Confirmo is a crypto payments processor: merchants take payment through its checkout, plugged in by API, and it moves about $750M a year. The checkout is a phone-sized flow, the same on a merchant’s website and on a phone. It is live, and the demo runs it without buying anything.
The shipped checkout, in one row: select token, select network, pay, processing, paid.
last-shipped-01 to 10 (v5), in flow order; the cover is his newest shipped UI. Subscriptions is not here; it closes the page.
The problem
Volume had grown from $63M to $750M a year in three years, about 60% of prop trading payments worldwide. One flow carried all of it, reverse-engineered from the crypto invoice spec, and it succeeded 9% of the time. Card checkouts run above 90%. Crypto averages 24%. People who want to pay usually find a way; here, most didn’t.
That was the problem: a 9% success rate. The backend was the constraint. Its invoice carried three quarters of a billion dollars a year and nobody was going to rebuild it mid-flight, so whatever I found had to live in the frontend.
The checkout I inherited: every screen, stacked, one screen doing everything.
inherited-01 to 14 (08 and 12 are pictures, in images/confirmo). Small labels on the screens: payment methods stacked on one screen; the instruction text in orange; the Expired clock in red.
9% success on $750M a year. The backend off-limits.
The cause
$680M a year failed to convert across only three steps, too few for analytics to isolate a cause. I mapped every screen, ran workshops with Sales, Engineering and Product, and read Customer Support’s complaints against usage. The loudest complaint became the starting point: the back button didn’t work.
The hand map: the three backend steps, and every screen and state found between them.
Reuse the live page’s map (the PAYMENT v2.4 / v11.1 / v21.8 pins, Portfolio/confirmo), restyled on this page’s grey; small labels only.
Impossible, as it turned out.
Users sending the wrong token or the wrong network.
The fiat figure sent in crypto, or a stale conversion.
Every way to pay stacked on one screen.
A failed payment looked like a waiting one.
The fastest way to pay, and the least reliable.
Tap one selects a token. Tap two selects a network, locks the rate, and creates the invoice. Invoices cannot be deleted or reversed, by design: a payment landing on a dead invoice is lost. Users trying to preview their total were pushed to a new screen with no way back. The trigger was the problem, not navigation.
The obvious fix was to change the trigger: create the invoice once the user commits. But the invoice is load-bearing. Its guarantees keep an irreversible payment from missing its target. I came up through engineering, so I know a hard no from a lazy one, and I checked this one with the engineers: save the choice, reset the rate, re-apply the picks for a fresh rate. Every route dead-ended in twelve years of legacy. This was a hard no.
The two taps, as a diagram: token, then network, and the invoice created on the second.
To draw, small labels only: tap 1 · tap 2 · rate locked · invoice created · no way back.
What was needed: a back button on the second step. What I built: a forward button on the first.
The bets
At a 9% baseline, shipping fast was nearly free: there was very little left to lose. So every fix became a version, and every version that could ship went to test markets and was read on live signal. I found 78 things to fix in the audit and fixed 59 of them in the first pass. The rest waited for later rounds.
The six versions, one row each, in order. The loud early ones small, the shipped ones large.
v1 inherited-01 to 14 (small) · v2 yellow-01 to 16 (small) · v3 breadcrumbs-01 to 16 (small) · v4 first-shipped-01 to 08 (large) · v5 last-shipped-01 to 10 (large) · v6 wallet-preload-01 and 02 (two mocks). Version labels as small captions, nothing else.
An exploration, coloured so it could never ship by accident. It built the back button, and that is how I learned the backend lock made it impossible.
Non-critical information moved to a hidden support screen, payment methods given their own room, and breadcrumbs. Breadcrumbs taught users they could go back while the mechanics still forbade it. Stuck again, now frustrated.
The mechanics that worked, in a shape and colour closer to the live product. The breadcrumb became a button that holds the selection and only advances when tapped. It worked.
A regulation now required an email and personal details inside a crypto checkout. Tested at the start and after payment, in similar markets. Both cost drop-off, as asking for identity on a crypto payment would. Only the back held people’s money hostage, spiked support calls for refunds, and cost us the fees. Front shipped.
With the button proven, I moved the Travel Rule step to the middle: after the buyer has chosen a token and a network, before any money has moved. It gained again. This is the version that raised success and the one the demo runs.
Where it was heading once success had earned a backend change: connect the wallet first, read which tokens it holds, preload the one that covers the total. One tap when every guess is right. Never shipped. The token reading came back in Subscriptions.
The Travel Rule step in its three places: the same screens with the form at the front, at the back, and in the middle.
Front: travel-rule-02 (the email sheet over Select token). Back: travel-rule-01 (the extra “Verification required” screen that placement needed) with travel-rule-03 and 04. Middle, v5: travel-rule-v2-09 to 11. No figures on this picture; none exist.
Beside it: Cable, the same move two years earlier, at desktop width. Four versions, v0 to 3.0, for banks, each justified by what the one before strained, until a free pilot became the first paying client.
From the public Cable page (cesarxdesign.com/cable): one desktop screen per version or the 3.0 suite; one line; the link.
Context must be precise and fair. Ask for what you need when the person has a reason to give it, and never when their money is already gone.
The trade-off
The old flow moved on by itself: tap a network and you were on the payment screen with an invoice behind you. Taps now save the selection locally, so a buyer can preview any token and network pairing without the backend hearing about it. A new button holds that state and moves the flow forward only when tapped. On commit, the saved selection is sent wrapped as the original trigger. The backend never knew.
The cost is a tap. Checkout design is mostly about removing taps, and I added one, on purpose. What it bought: nobody is pushed into an irreversible step any more. People could still get stuck on the next screen, but they arrived there of their own accord, with a total they had already seen. Better beat perfect, and the backend was not something I could change.
The button, large, in its three states: asleep, waking, live.
first-shipped-01 to 03 or last-shipped-01 to 03, cropped to the button and its labels: ASLEEP, nothing chosen yet · WAKING, token picked, network pending · LIVE, ready, waiting on the user. Reuse the live page’s treatment.
Step one: it stores the selection and advances the flow when the user is ready. Step two: it carries the money: fiat price, exchange rate, conversion, and the total to pay. Step three: it stays on screen as a reference while the payment completes.
Beside it, at desktop width: Starcount, where an accurate map put 90% of the visibility on London, and the right map broke the rule too. Both decisions pay a textbook cost on purpose.
From the public Starcount page (cesarxdesign.com/starcount): the map at full column width; one line; the link. Wording matches the CV.
Nobody is pushed any more. They go forward when they’re ready.
What shipped
The shipped checkout is five steps for the buyer: select token, select network, pay, processing, paid. Everything that used to fight for space on one screen has its own place. Payment methods are tabs. Support and language live on a secondary screen, one tap away and out of the way. The countdown is always visible. Expired is not an error: the invoice just runs again.
v5 in full, every screen in order, with its way in and its way out.
last-shipped-01 to 10. Craft labels on the screens, small: numbers in a true monospace, so 1111 never looks like less money than 888 · payment methods as tabs · the support screen · the countdown · Expired.
After payment, anything could happen: processing could fail by token and by network, the timer could run out, a buyer could underpay and sit on the payment screen waiting, or overpay and be offered a refund that needed a form, and sometimes didn’t cover its own fees. Twelve paid states, each a different screen, each a slightly different design. I replaced them with one: the processing screen carries a log, and each entry can carry its own action. Request a refund. Enter the details. Pay the remainder, which takes you back to the payment screen with the values updated. The buyer stays on one familiar screen and reads what to do next.
The twelve old paid states, small, against the one log.
images/confirmo/paid-01 to 12 in a tight grid; beside them last-shipped-09 (processing, with the log) and log-expired-refund (“Invoice expired with payment” with Request refund inside the entry). Not the Travel Rule “Verification required” screen.
Everything that fought for one screen got its own.
The outcome
In test, the best markets went from 11 to 12% success to 43% over a couple of weeks. Then it shipped worldwide: 9% to 27% overall, above the 24% crypto average. Converted payments rose from about $67M to $202M a year, $135M added, out of the same pool of merchants and buyers as before. No new merchants, no ads, no sales push. The checkout stopped leaking.
Key markets, over a couple of weeks.
The average after the global launch. The best markets stayed higher.
$135M added, zero backend changes.
The flow is live. Confirmo’s checkout demo runs it from Select token.
Same flow, same constraints, same data, same pool of buyers. A different result.
Subscriptions
The result funded the next product: Confirmo Subscribe, recurring stablecoin payments, launched on 14 July 2026 on Solana and Polygon with USDC and USDG, and the first stablecoin subscription product to support both exchange accounts and self-custody wallets. It was the first project there designed with AI from the first wireframe. The brief was simple as a UX problem. The process is the point.
The progression: the wireframes, v4, v5, v6, one row each, the last one largest.
subs-wf-01 to 06 · subs-v4-01 to 07 and 02b · subs-v5-01 to 07 and 02b · subs-v6-01 to 08. White-label, neutral, action colours only; the token and network logos bring it to life. v6 at full size, the earlier rows small.
The first attempt went straight to high fidelity. It looked proper, and I had no ownership of it: I couldn’t explain it, so I couldn’t work on it. I stepped back. That was not where AI could help.
The product requirements ran long and were written for everyone in the company. AI pulled out exactly what design needed.
The first wireframe was not a good flow. It was every relevant piece of the requirements, in view, in steps. From there, rearranging it into a better flow was fast, and a few rounds later we had a wireframe checked against the requirements for blind spots.
Prototyping the wireframe was nearly instant, so PM and stakeholders saw a working flow early, and tuned it while it was still cheap to change.
Clients wanted out of the brand colours, so the language is neutral with action colours only; the logos carry the colour. Shadows, pulsing dots, tuned transitions. “A hair thinner” worked. So did “24px radius”. Batch changes stopped being the thing that plagues early design.
Built into Figma by Claude. Everything before it was overwritten before I knew to save it.
The prototype was faithful enough, with real mock data and at one point real wallets, that internal testers and FTMO used it like production and went off the script. Someone picked a token we hadn’t planned for and had no balance. Tests are set up for success; this one wasn’t. That is where Refresh balances comes from, in v5.
And the warning moved to the accent colour, as in the checkout. v6 is the last version, and the one the prototype runs.
Prototype: Subscriptions v6, to click through.
subs-v6-01 to 08. The rule is in the screens: Refresh balances shows only when the selected token or network has no balance; with at least one good option it is hidden (02 has no button, 03 has it). Eight screens cover some forty permutations. Ships only when every tap is wired and tested; otherwise the flow laid out.
The speed makes it easy to skip a proper component structure, so a change to one component didn’t always reach the other places it lived, and I found that later. Not knowing what sits behind the pixels, AI would hack through animations and masks in ways that weren’t fit for handover, even if the developers were then using AI to turn it back into code. The process is faster and freed of a lot of friction. How hard to push it is something we were still learning.
The loop, for what it’s worth: the requirements I received came out of AI, what I designed went into Figma through AI, and the developers turned the Figma back into code with AI. Even with all that overhead, it was a lot faster.
Subscribe launched. I left that month, so the numbers after launch are not mine to report.
AI laid out the puzzle. The flow, the look and the edge cases were still mine to get right.
It couldn’t be done.
That’s no reason
not to fix it.