Svetlozar Apostolov
Payments UX · B2B white label

A payment surface that configures itself

One deposit and withdrawal interface, embedded into many different client websites. Each client wants a different layout, a different density and a different set of payment methods — and none of them wants a bespoke build.

Role
Senior designer, then design lead
Period
Oct 2024 – present
Working with
Design, front end, back office
Status
In design and implementation

The problem was never the screen

Stripped to its barebones logic the product is close to a digital wallet: put money in, take money out, see your history of either. What makes it hard is that it is white label. It is embedded into someone else’s website, styled to someone else’s brand, and populated by whichever payment methods that client has enabled in a back office.

So the design question is not what the deposit screen looks like. It is:

  • Which differences between clients are worth supporting as configuration?
  • Which differences should the system decide, so a client cannot break the experience?
  • Can a single component set absorb all of them without forking into separate products?

Every option we expose is a support cost forever and a way for a client to make the product worse. Every option we withhold is a sales objection. That trade is the actual design work.

Choose a methodDeposit
The two surfaces that carry the product: a lobby of payment methods, and the deposit form behind whichever one is chosen. White-labelled — provider marks and currency removed.

How the widget is structured

The widget is a sequence of four stages: lobby, form, intermediary steps such as 2FA, and end flows (receipt or error). Every stage sits inside the same three-level wrapper, and each level owns exactly one thing.

Shell · full page, drawer or modal Container · default or compact LobbyPick apayment method FormAmount, storedinstrument, bonus Intermediary2FA(optional) End flowsReceiptor error Every stage lives inside the same wrapper. The wrapper never knows what is inside it. Shell · full page, drawer or modalContainer · default or compactLobbyPick a payment methodFormAmount, stored instrument, bonusIntermediary2FA (optional)End flowsReceipt or errorEvery stage lives inside the same wrapper.The wrapper never knows what is inside it.
Four stages, one wrapper. The shell and container are configured once for the whole widget.
The three levels of the wrapper
LevelOwnsNever owns
ShellWindow type, width, scroll, how it is dismissedAnything about the content
ContainerComponent sizing, as a swap between two dimension token modesStructure, order or what is visible
ContentThe stage’s own screensThe window or the sizing

One master shell and container setting applies to every stage. A stage can override it, but only where there is a known use case. Unlimited per-stage override multiplies the combinations someone has to test.

The configuration matrix

Five axes, chosen after mapping what clients had actually asked for against what the component architecture could carry without splitting into separate products.

Mode3Full pageDrawerModalDensity2DefaultCompactLobby layout4RowsMixedCardsGridForm layout4AlphaBetaCharlieDeltaBonus offers2ModalInlineOne client deployment. There are 191 others.Mode3Full pageDrawerModalDensity2DefaultCompactLobby layout4RowsMixedCardsGridForm layout4AlphaBetaCharlieDeltaBonus offers2ModalInlineOne client deployment. There are 191 others.
The diagram that made the scope legible to stakeholders. Before it existed, every conversation was about one screen.
Configuration exposed to clients through the back office
AxisOptionsWhy it is configurable
Mode3Full page, right-hand drawer, or modal over a dimmed page. Depends entirely on how the host site is built, so it cannot be a system decision.
Density2Default and compact, driven by a spacing token scale rather than redrawn components.
Lobby layout4Clients have wildly different numbers of payment methods, and eight methods and forty methods want different layouts.
Form layout4Four arrangements of the same amount input, saved-card selector and bonus block.
Bonus offers2Modal or inline. A commercial decision about how hard to push offers, so it belongs to the client rather than to us.

A third bonus presentation, vertical, was built for one client and is queued as a new value on this axis.

192valid combinations from one component set, one token scale and one set of business rules

What stayed locked

The more useful half of the matrix is what is missing from it. Each of these was deliberately not exposed, and each one is a conversation I had to win.

  • The shell. Deposit, withdrawal and history always sit in the same tab bar in the same position, and the compliance footer is always last. Clients can restyle it. They cannot rearrange it, because it is the only thing that stays constant while a user moves between payment methods.
  • Step order. Method, then amount, then instrument, then confirm. Clients asked to reorder this. Reordering it breaks the validation model and every error state that depends on it.
  • Spacing values. Density is a choice between two token sets, not a free numeric field. The moment spacing becomes an input, the design system stops being able to guarantee anything.
  • Overlay type. Secondary overlays, such as saved cards or bonus selection, are sheets on mobile and modals on desktop. Never interchangeable, never a client choice.
  • Error and empty presentation. A misconfigured lobby with no enabled methods still has to say something useful. Leaving that to the client guarantees a blank screen in production.

Form variants are presets, not designs

The four form variants look like four separate designs. Pulled apart, each one is a fixed combination of values across six independent axes. That reframing is what lets a new client request be absorbed without drawing a fifth form.

Each variant is a different combination of choices along the same few axes, such as how an amount is entered, how a saved method is picked and where the main action sits. Change one choice and you get a different form without redrawing the rest.

The rule that follows: a client customisation has to land as a new value on an existing axis. A new lobby layout and a vertical bonus layout were both built for a single client, and both ship as options any operator can switch on. If a request fits no axis, that is the signal to stop and decide whether a new axis is warranted, rather than slipping in a special case.

Arrangement and content are different questions

Operators choose how a form is arranged. They do not choose what is in it. That is decided by the payment method, and there are 50+ methods. So each method is assigned to one of a handful of typisations. Methods in the same typisation reuse the same blocks, rules and screen sequence, for deposits and withdrawals alike.

A rendered form is therefore three independent choices: form variant, typisation and direction. Neither of the first two is nested inside the other, so an account-based flow in Alpha and in Delta has the same blocks and the same rules, arranged differently.

Typisations, a selection
TypisationWhat it isTypical methods
StandardAn amount and a submit button. Nothing else.50+ methods
Card basedSaved card, add new card, delete card.Credit and debit cards
Account basedTied to a player account, with shared add, select and delete logic.E-wallets, bank accounts
And moreA few others exist. Not shown here.—

The practical effect is that adding a payment method becomes an assignment rather than a design task. If a method fits no typisation, that is a decision point: extend one, or create a new one on purpose.

Responsive behaviour as a design decision

The four lobby layouts are not four breakpoint sets. Each is a different answer to the same question — how do you make a list of payment methods scannable — and the breakpoint behaviour follows from the answer.

RowsRows on bothMixedRows, then cardsCardsCards on bothGridGrid on bothRowsRows on bothMixedRows, then cardsCardsCards on bothGridGrid on both
Mixed is the one worth defending. Cards on a phone eat vertical space and truncate exactly the text a user needs to identify their bank. Rows on a wide desktop waste the horizontal room and make a short list look empty. Switching representation at the breakpoint is more work to build than picking one, and it is the right answer.

Anatomy of the deposit form

Four elements, each more conditional than it looks.

  • Amount input. Sits alongside preset amounts the client configures. Presets and field must stay in sync in both directions, and the field has to tolerate limits that differ per method and per user.
  • Instrument selector. One container that is either a saved card, a chooser between several, or an invitation to add the first one. Three quite different states behind one affordance, because splitting them creates three layouts for one job.
  • Bonus mechanic. Either a list of eligible bonus offers or a bonus code field for personalised codes, with a segmented switch between them. Eligibility depends on the amount input field, so the mechanic reacts while the user is still typing.
  • Confirmation. After submission there is a gap while backend checks run, and only then a receipt. That gap is the riskiest moment in the product, and it gets a real state rather than a spinner over a frozen form.

Edge cases

Most of the design time went here rather than into the happy path.

  • Methods that only support deposits, or only withdrawals, sharing one lobby without making the user discover the restriction after they have already committed to a choice.
  • A lobby with nothing enabled, because someone misconfigured the back office.
  • A backend check that fails after submission, when the money may or may not have moved.
  • Amount limits that vary by method, so preset buttons can be invalid for the method just chosen.
  • A bonus that becomes ineligible as the user edits the amount downward, after selecting it.

How it is documented

The system lives in three working documents, each answering one question:

  • Design logic. What the building blocks are: tokens, components, their properties and states, and how they map to code.
  • Layout logic. Which layout uses which components, and why, including a constraint matrix of which combinations are valid.
  • Form logic. What each typisation contains, block by block, and which screens it owns from start to end.

Every claim in them carries a status: confirmed, draft or open. That is the point of the exercise. A guess that is not marked as a guess gets read as a decision, and by the time anyone notices it has been built.

What I would measure

This shipped without instrumentation. The team was structured to deliver requested features, not to evaluate them, and no success metrics were kept. I am not going to invent numbers for a portfolio. What I would have put in place, in priority order:

  • Completion rate by payment method. The single number that says whether the lobby is helping, and the one that would settle the Rows-to-Grid argument with evidence instead of preference.
  • Drop-off between lobby and form. Isolates method selection from method completion. High drop-off here means the lobby is promising something the form cannot deliver.
  • Error rate on amount entry, split by whether presets were used. Directly tests whether the preset buttons do their job or just add noise.
  • Saved-instrument reuse on repeat deposits. The clearest signal on whether the selector’s three states are legible.
  • Time from submission to receipt, and abandonment inside that window. The gap I was most worried about, and the one I had no way to see.

Setting this up would not have been expensive. It was never asked for, and I did not push hard enough for it. That is the thing I would do differently.

NextA roulette table you can bet on the edges of