Skip to content
The original rosewood identity: plum, coral, and bronze.
Work

World Vision

World Vision

White-label donation platform for partner organisations running their own branded versions on top of World Vision's infrastructure.

Off-limits

donation volumes

Role
Lead Design Engineer
Period
Oct 2020 – Apr 2021
Engagement
embedded
Tech
Nuxt / Vue / Braintree / Multi-tenancy

Six months building a donation engine that had to look like several different partner organisations from one codebase. Nuxt on the front, Braintree on payments, multi-tenancy in the data layer rather than scattered through controller logic.

The tenant model

The tenants weren't World Vision regions or country offices. They were partner organisations, larger corporate or charity donors that ran their own branded donation experience on top of World Vision's infrastructure. Each got its own surface, its own brand, its own donor relationship. World Vision provided the engine.

Tenant configuration sat in data. Each partner got its own row, its own brand identity, its own copy, its own payment processor settings, its own receipt templates. Onboarding a new partner was a config change, not an engineering project. That distinction is the whole story. When the configuration is the contract and the code is the engine, the team running partner relationships can spin up a new branded surface without filing a ticket, and the engineering team isn't pulled into every brand refresh.

The trap in white-label work is letting tenants leak into the codebase. One conditional becomes ten. Ten becomes a graveyard of `if (tenant === 'xyz')` blocks that nobody understands six months later. The discipline was to refuse that drift on day one. If something needed to vary by partner, it varied through configuration. If it couldn't vary through configuration, the question was whether the variation was worth keeping.

Rendering by partner

Each tenant rendered its own surface from a shared component layer. The components didn't know which partner they were inside. The tenant context did the lifting: theme tokens, copy strings, payment methods, receipt formatting. Nuxt handled the routing and the SSR layer cleanly. The donor on the other end saw the partner's brand, the partner's framing of the cause, the partner's payment options. Underneath, a single render path.

Each partner organisation had its own identity and its own editorial voice. The platform respected that. A donor giving through one partner was supposed to feel like they were on that partner's site, not on a generic donation form with someone else's logo bolted on. The visible surface had to feel like the partner's. The infrastructure underneath had to be unified. Both things at the same time, without compromise to either.

Braintree, plumbed properly

Payments went through Braintree. The work there was less about integration and more about isolation. Each partner had its own merchant account, its own fraud rules, its own receipt templates. The donation flow normalised the inputs and routed to the right account based on tenant context. Failure modes were explicit: card declined, processor timeout, fraud flag. Each one had a path back to the donor that respected the moment they were in. People donating in response to a crisis don't need a generic error page.

Recurring donations carried their own state machine. Sign-ups, renewals, failed retries, cancellations, lapse recovery. The tenant layer extended through that state machine too, because retention copy and retry cadence varied by partner.

What I can't say

Donation volumes. Fundraising numbers. The dollars are off-limits.

Outcome

Shipped. Multiple partner organisations running through one codebase, each one looking and behaving like its own thing. The configuration-driven tenant model held up through new partner onboarding without code changes, which was the bet at the start of the project and the proof at the end of it.

Role
Lead Design Engineer
Period
Oct 2020 – Apr 2021
Engagement
embedded
Tech
Nuxt / Vue / Braintree / Multi-tenancy

© 2026 Robert Andrew, Melbourne, Australia.

Robert Andrew

Design. Build. Ship. Repeat.