Tom Neal

Cloudli Partner Portal

The Cloudli Partner Portal is one place where partners take a prospect from quote to paying customer, with a flow that adapts to how each partner works. Customers then onboard themselves through a guided flow, with their partner able to jump in and help.

One joined-up journey to replace a tangle of fragmented processes.

I led the design end to end. We built two connected pieces: a Partner Portal, where a partner takes a prospect through quoting to a signed sale, and a collaborative customer onboarding flow that picks up the moment that sale is approved. According to our Sales team and Head of Onboarding, onboarding came down from several weeks to just a few days.

Role

Product Design Lead

Platform

Web SaaS

Team

1x Head of Product

1x Product Designer (me)

3x Backend Engineers

2x Frontend Engineers

Reading control

Show me everything

~ 10 min read

The problem

Too many tools, emails, calls…

Picture being one of Cloudli's partners. You resell our services to your own customers, but quoting, sales, onboarding and account management each live in their own tool (NetSuite among them) or in someone's inbox. Getting a single customer live means hopping between systems, firing off emails and chasing details the customer could have entered themselves. Let's just say things were slipping through the cracks.

A high-level view of the fractured process

3 partners with very different needs

To make things more complicated, not every partner worked the same way. Some set their own prices, some needed sign-off, and some didn’t want their customers to know Cloudli existed at all. The challenge was organising all the pieces of the puzzle into one journey that was flexible enough for everyone.

My role & team

A team of 7, with me owning the design from first doodle to final pixel

As Product Design Lead and sole designer, I was deeply involved at every step, from speaking with users and stakeholders, mapping the workflows and journeys right through to detailed UI and the design system. I didn’t have designers reporting to me, so for me leading meant taking ownership of design, and communicating it effectively to influence decisions across the team.

It was a tight-knit team: 1x Head of Product, 1x Product design Lead (me), 3x Backend Engineers and 2x Frontend Engineers, who I’d pull into conversations early and often. We also worked closely with the Sales and Marketing teams, who knew the existing process (and all its quirks) inside out.

Approach & research

Getting aligned

Nine times out of ten everyone’s got a slightly different version of the problem, so the first job was getting us all agreed on what we were actually solving. This involved identifying the various steps a Partner would move through to get a prospect converted to a paying customer, including the pain points for each process and system, then mapping them out visually so we had an overview of where friction occurred.

Mapping out some primitive user flows

Speaking with partners

I interviewed staff from three partners of varying types to understand needs and gauge cognitive load, making sure each step was easy to understand and split into manageable chunks.

  • Agent partners needed to quote prospects and get approval from the Cloudli sales team before converting them to paying customers.

  • BoB (bill on behalf) partners needed the ability to adjust pricing when quoting their customers, and didn’t need approval when submitting a signed quote to convert a prospect.

  • Wholesale partners needed a fully white-labelled experience, so their customers appeared to buy directly from them, with Cloudli hidden as the middleman.

Sharing is caring

I captured what we heard from partners in Notion, and fed it into a shared Confluence space so the whole team could see the insights behind each decision. I mapped the end-to-end journey in FigJam, noting where it needed to bend for each partner type and where we could automate or remove steps altogether. Flows and scrappy prototypes went to Product and Engineering as soon as there was something to react to, and while changing direction was still cheap.

Challenge A: the partner portal

One flow, different rules

Partners create a prospect, build a quote and convert it into a sale in a single guided flow. Behind the scenes it talks to several third-party systems, but partners just see one clear path.

Rather than building separate journeys for each type of partner, the flow adapts. Our BoB partners can adjust pricing, so the quote reflects what they’re actually charging, and progressive disclosure means each partner only sees the options relevant to them. The same goes for the finish line. Once the customer signs, the partner submits the signed quote to convert the prospect. Where a partner needed sign-off, it went through approval first, while BoB partners skipped that step entirely, so a signed quote turned their prospect straight into a paying customer.

That approval is the baton pass. It’s what kicks off customer onboarding in Challenge B.

BoB partners can adjust pricing for their customers

Waiting… waiting… waiting for NetSuite

When a partner created a quote, NetSuite had to build an opportunity and hand back an ID before they could continue, and that could take anything from 2 to 10 seconds. 10 seconds doesn’t sound like much until you’re staring at a frozen screen wondering if you’ve broken something. And it was completely out of our control.

So we focused on what we could control: setting expectations, communicating clearly and always giving people a way forward. Through research into UX laws around waiting time and working with Engineering, we landed on a graduated loading experience. I created AI prototypes in Cursor so we could test the timings with real delays before committing to them. For short waits, an inline loading bar does the job without interrupting the flow. If it goes past 2 seconds, it switches to a modal spinner with extra context explaining what’s happening, so partners know it’s still working. And if it fails, the error is explicit about exactly what went wrong, with a clear option to retry or reach out to support.

We also weighed up a few alternative options, including a single blocking spinner. It was the simplest to build, but at 10 seconds with no context it feels broken, and people tend to refresh or click again mid-quote. Creating the quote in the background and notifying partners later sounded slick, but it was a lot of extra complexity for our small team, and it risked partners acting on a quote that later failed. Caching or pre-fetching was a non-starter, as the ID was created by NetSuite in the moment, so there was nothing meaningful to cache.

Graduated loading won because it matched the feedback to the length of the wait, kept partners informed and always gave them a way to recover, while being realistic for our team to build. Good UX isn’t just about the happy path; it’s designing for the moments when users can’t see what’s happening behind the scenes.

Graduated loading in action

Settling a standoff with a single hex code

Our Wholesale partners needed a fully white-labelled experience, which led to a classic standoff. Our Head of Product was pushing for individual themes based on each partner’s branding, while Engineering, understandably, saw a potential drain on time and resources to build and maintain all those different versions.

Rather than picking a side, I went back to what we actually needed to achieve. Each partner should feel like the product was theirs, but we didn’t need a completely separate theme for every one. So I proposed a dynamic theming system: the partner enters their primary brand colour as a hex code in their portal, and it’s mapped automatically onto key elements like buttons and labels. A Tailwind API takes that single hex code and generates a shade scale, so we could make sure there was enough contrast between a button and its label. I set up a new “themes” variable collection in Figma that works across both light and dark modes, keeping design and code aligned.

The Wholesale partners got the branded experience they needed, Engineering didn’t get buried in extra work, and everyone was happy. I’d much rather walk away with a better solution than be able to say I won the argument.

🧙‍♂️ One hex to rule them all

Challenge B: customer onboarding

Onboarding, but make it a team sport

As soon as a sale is approved, the customer’s assigned account owner automatically gets an email with a link to the onboarding flow. That took a lot of the onus off partners, who no longer had to go back and forth with customers gathering information the customers could perfectly well enter themselves.

Handing it over didn’t mean leaving customers to it, though. Speaking to partners, it became clear there was no one-size-fits-all here. Some customers were more than happy to onboard themselves, while others still wanted their partner to handle it, and some partners preferred to do it on their customer’s behalf anyway. So rather than forcing one approach, we made onboarding collaborative and let either side pick it up.

We designed onboarding to save progress at each step, so you can pause to grab a coffee, or step away completely without losing anything. And because it’s shared, the partner can open the same onboarding flow and help wherever the customer is stuck, rather than trying to talk them through it over email.

Onboarding is broken down into manageable chunks

Bulk import without the spreadsheet dread

Adding users one by one doesn’t scale, so account owners can bulk-upload users and their existing phone numbers by CSV. They download a formatted template, fill it in and re-upload it. Rather than a blunt pass or fail, the data appears in a worksheet view with any invalid or unexpected cells flagged, so problems are easy to spot. If they try to continue with issues remaining, we highlight the problem cells and give them a clear choice: go back and fix them, or proceed with the X entries that passed validation.

One bad phone number shouldn’t block fifty good users, but we also didn’t want anyone breezing past errors without noticing.

Uploading users and handling errors

The right access from day one

Once users are in, whether imported or added manually, the account owner gives each one a permission level. Everyone defaults to basic, so the owner only has to change the exceptions.

There are three levels, each with a short plain-English description so account owners don’t need a telecoms glossary to pick one. Basic users can change their own account and telephony settings. Restricted users can’t change anything and are managed entirely by admins. Admins can change account and telephony settings for themselves and everyone else.

The timing mattered as much as the levels. Setting permissions before provisioning meant that when the accounts were ready to use, users had the correct access from day one, rather than everyone going live and the owner tidying up access afterwards.

Setting roles is clear & simple

Design system

A shared foundation, built in Figma, to hold it all together

Confession time: I’m a bit of a design system nerd. Naming tokens, structuring variables, getting a button to behave in every state? That’s my idea of a good afternoon (yes, I’m weird)!

Underneath it all, I curated a design system in Figma, using Shadcn as the foundation so design and dev were speaking the same language from day one. On top of that sat our own reusable components, tokens and patterns, with variables powering light and dark modes and an extra theme layer for white-label partners. Swapping the brand variable mode makes every component follow suit.

WCAG AA was a key standard throughout, with contrast checks baked into the theming and font sizes that prioritised readability.

Shadcn to kick-start, and theming tokens built on top

Impact

Onboarding went from several weeks to just a few days

That's according to feedback from our Sales team and Head of Onboarding, which made for happier partners and customers.

Partners got one place to work

Prospecting, quoting and converting a sale moved from a tangle of separate systems, calls and emails into a single flow, resulting in a common sales process and a reduction in loose ends.

Partners stopped playing piggy-in-the-middle

Customers could enter their own details, and partners could jump in wherever they were needed, rather than chasing information back and forth.

White-labelling scaled without the overhead

One hex code replaced a theme per partner, so new partners got their brand without adding to Engineering's workload, and the contrast checks kept it accessible.

Cleaner data with fewer surprises

CSV validation caught bad data before it went anywhere, and good rows never got held up by bad ones.

Start with the right access

Permissions were set before provisioning, so customers' teams went live with the correct access, rather than an admin tidying it up afterwards.

A design foundation to build on

A WCAG AA design system with light and dark modes, with partner theming to give the team a consistent base for ever-expanding features.

On reflection…

If I were to work on this project again, there are a couple of things I'd look deeper into:

Bring 10DLC into onboarding

10DLC is a US requirement for businesses sending texts from standard business phone numbers, and registering involves submitting business details for approval. Because of its complexity, it remained a manual process, requested after the customer’s account was provisioned. That meant another wait before customers could start messaging. I’d have liked to bring it into the onboarding flow, so registration could get underway while the account was being provisioned, with the two running in parallel rather than one after the other.

Define brand colours against semantics

With dynamic theming, a partner with a red brand colour gets red buttons, and red tends to say “error” or “warning”. It never caused a problem, but if I took it further I’d separate brand tokens from semantic colours (success, warning, error), with clearer rules around what brand colours could be used, and test the theming against some more extreme examples.