Case study
HapplyOS
Turning one platform into every funding organization's own.
Senior Product Designer · Feb 2025 to present · Product design, design systems, UX writing · B2B SaaS, white-label

At a glance
Role
First and only product designer. Every screen and component on the organization side is my design, from the member portal to the back office. UX decisions on a few areas were made together with Rosie, the PM; the rest I owned.
Team
Rosie (PM), three engineers, the CEO for client requirements, and me.
Timeline
Feb 2025 to present. I wrote the HapplyOS platform overview first, then designed each module against it.
Status
Pre-launch. Designs are complete and in build; the back end is in progress.
Scope
Members and groups, programs and applications, the review queue, roles and permissions, the Education Center, events and bookings, reporting, tenant theming, 42 transactional emails in two languages, and the component library under all of it.
What changed
Made groups the unit that access, enrolment and reporting key off, so a cohort of three hundred is one import and one assignment.
Kept the AI fit score advisory: visible and sortable, with every decision recorded against a reviewer’s name.
Made every half-finished state in the back office a valid, saved state, starting with the course builder.
Merged three visual languages into one component library that themes per tenant.
What HapplyOS is
Happly has two sides. Founders use Seeker to find funding. The organizations that hand out that funding, economic development agencies, accelerators, industry associations, use HapplyOS to run their programs: members, applications, review, courses, events and reporting, on a portal that carries their own name, domain and brand.
It is the half of the product nobody outside the company sees, and the half that decides whether a client renews. Every client wanted the platform to look like theirs and behave like theirs.
The organization side, counted
3 → 1
visual languages merged into one library that themes per tenant
Save
Save
Save
Three styles
→
Save
One library
7
modules designed on one codebase, from members to reporting
Back office
Members and groups
Programs and applications
Review queue
Roles and permissions
Education Center
Events and bookings
Reporting
42
transactional emails written in one voice, in English and French
English
01 02 03 04 05 06
07 08 09 10 11 12
13 14 15 16 17 18
19 20 21 22 23 24
25 26 27 28 29 30
31 32 33 34 35 36
37 38 39 40 41 42
French
01 02 03 04 05 06
07 08 09 10 11 12
13 14 15 16 17 18
19 20 21 22 23 24
25 26 27 28 29 30
31 32 33 34 35 36
37 38 39 40 41 42
Each count drawn as the thing it counts: a button, the sidebar, the template register.
What I owned
I am the design owner for the whole HapplyOS side, working directly with the PM, the CEO and the engineering team.
Members
Import, invites, groups, personas, profiles, internal notes and file requests
Programs and applications
Program creation, custom questions, one-click apply, the review queue and AI fit scoring
Roles and permissions
Custom roles with per-module see and do rights, and how a locked action looks
The Education Center
Courses, lessons, quizzes, assignments, certificates, self-paced and structured modes
Events
Mentor meetings and room bookings, with free and paid ticketing
Reporting
Dashboards, custom onboarding questions, tenant theming, and the component library underneath all of it
I also wrote the HapplyOS platform overview the team works from, then designed every module against it.
Admin tools get the most use and the least design
Every organization on HapplyOS runs the same shape of work: bring people in, put them in programs, review what they submit, teach them something, and report on it. But each one had a different membership model, different eligibility rules, and a brand they were proud of.
The platform had grown one client request at a time. Screens existed for most things and a system existed for none of them. Admins managed people one row at a time, reviewers were handed an AI score without knowing what to do with it, and a course could not be saved until every field was filled.
“Groups are not just labels. This is what stops the platform becoming a spreadsheet with extra steps.”
From the HapplyOS platform overview I wrote for the team.
Decision one: groups are the lever
The problem
An organization might have three hundred members across four programs and two cohorts. The obvious admin tool is a table of people with checkboxes. It works for thirty people and collapses at three hundred, because every decision about who sees what has to be made again for every person.
Who sees what, set two ways
Per person
300
people, and the same decision made again for each
Per group
Cohort
Programs
Courses
Events
Content
Reporting
1
assignment, and the platform does the rest
Per person, the same choice is made three hundred times. Per group, once.
The decision
Groups became the unit everything else keys off. A group decides which programs a member can see, which courses they are enrolled in, which events they are invited to, which content they can read, and which slice of the reporting they show up in. Assign someone to a group and the platform does the rest.
Bulk import follows the same logic. An admin uploads a spreadsheet, sees the first rows parsed back before anything is saved, gets a downloadable file of the rows that failed, and chooses whether to email everyone now or stay silent until the program is ready.
Personas sit on top of groups, so an organization can tag someone as a founder, a mentor or a partner and route content by that as well.
On import
Email everyone now
Stay silent until the program is ready
Silent import selected: no welcome email goes out until the program is ready.
Why
An admin’s real question is never “what can this person see.” It is “what does this cohort get.” Groups answer the question the way it is actually asked.
The silent import option exists because the worst first impression a program can make is three hundred welcome emails sent before the portal is finished.
Members: bulk import preview and group assignment
Assign a group and the platform decides what the member sees.
What it changed
Access, enrolment, invitations and reporting all resolve from one assignment. Setting up a cohort of three hundred is one import and one group, not three hundred rows of checkboxes.
Groups also became the model the engineering team built permissions and content routing on, so the admin mental model and the data model are the same thing.
What we said no to
Per-person visibility toggles. They were requested because they feel precise, and they are the reason admin tools collapse at scale. If someone needs an exception, they get their own group.
Sending welcome emails on import by default. The silent option was argued against as an extra step. It stayed because one client sending three hundred emails to an unfinished portal would cost more than the step ever will.
Decision two: a score with no button attached
The problem
Reviewers get a stack of applications and a deadline. An AI fit score sitting next to each one is tempting to treat as the answer, and the first time it is confidently wrong, reviewers stop trusting anything on the page.
The decision
The score is advisory. It sits beside the application with its reasoning, it helps a reviewer sort the stack, and it has no button attached.
Decisions are made by a person, recorded against their name, with the reviewer’s own notes.
Program questions never re-ask what the platform already knows about a member, so reviewers see the answers that are actually new.
From score to outcome
01 · Advisory
AI fit score
Visible, sortable, explained.
03 · Outcome
Yes or no
Recorded against a name.
Score → outcome
No path
The reviewer is the only stop between the score and the outcome.
Why
This is public and institutional money. Someone has to be accountable for a yes or a no, and it cannot be a model. So the score gets a place on the page and no power over the outcome.

The score helps sort the stack. The decision has a name on it. Demo data.
What it changed
Every decision in the review queue carries a reviewer’s name and notes. The AI fit score is visible, sortable and explained, and there is no path from the score to an outcome without a person in between.
The same rule now applies across the platform: on the founder side the match badge, on the organization side the fit score. The AI advises, a person decides.
What we said no to
An “auto-reject below a threshold” option. It was the most requested time-saver and the one thing that would have made the platform indefensible the first time a good applicant was scored low.
Hiding the score entirely. Reviewers with a stack of eighty applications do need help sorting. The score earns a place on the page, not a hand on the outcome.
Decision three: let people save half a thing
The problem
The Education Center lets an organization build courses with lessons, quizzes, assignments and certificates. The first version treated a course like a form: fill everything in, then publish. Nobody builds a course in one sitting, so nobody finished one.
The decision
Creation became progressive. A course can be saved with a title and nothing else. Lesson types are chosen by the content you have, not by a template.
Drafts warn about unsaved changes rather than blocking the exit. Quizzes allow unlimited retries and keep the highest score, so a quiz is a way to learn rather than a way to fail.
Notifications go out only for things a person can act on, never for automatic events like a quiz being scored.
Course
Saved as draft
✓
Course title
Lessons
Add when ready
Quizzes
Add when ready
Assignments
Add when ready
Certificate
Add when ready
Only the title is required. The empty slots are part of a valid draft, not errors.
Why
Admin tools fail quietly. Nobody complains, they just stop using the feature and go back to a PDF.
The way to keep an organization building courses is to make every half-finished state a valid state.

Every half-finished state is a valid state. Demo data.
What it changed
A course exists the moment it has a title. Lessons, quizzes, assignments and certificates are added when the content is ready, and leaving mid-way warns instead of blocking. Nothing an admin does is lost because they stopped for lunch.
“Every half-finished state is a valid state” became the rule for the rest of the back office too: program setup, event creation and onboarding questions all save as drafts.
What we said no to
Course templates. They looked like a shortcut and they would have forced every organization’s content into the same shape. Lesson types chosen by the content you have do the same job without the mould.
A single attempt on quizzes, which was the default in the first version. Unlimited retries with the highest score kept turns a quiz from a gate into a way to learn.
Everything else
Three decisions do not cover a platform with this many modules. The rest of what I designed on the organization side, in brief.
View ✓
Edit ✕
Roles and permissions
Custom roles with per-module see and do rights (view versus edit, per feature), so a partner organization can hand a reviewer the queue without handing them the member list.
Apply
One click
Programs and one-click apply
Program creation, additional questions that never repeat what the profile already holds, and a one-click apply that respects every application state the API already had.
Free
Paid
Events, meetings and bookings
Free and paid ticketing, mentor meetings tied to member assignment, room bookings by the hour. Member side and back office, desktop and mobile.
Dashboard
=
List
Reporting
Dashboards for program managers where every number is computed from the same source lists as the views underneath, so a count on the dashboard never disagrees with the page behind it.

The white-label side, here member management inside one organization. Each organization gets its own branding, domain, onboarding questions, roles and content access, on one codebase. Demo data.
Three styles into one
The platform had accumulated three visual languages. I unified them into a single component library, built on Radix primitives, that themes per tenant, so a funding organization gets its own brand without anyone forking the interface.
Components sheet or tenant theming comparison, two brand colours on the same screen
One library, themed per organization.
What I would do differently
I would have settled the permissions language earlier. The platform ended up with two ways of showing an action you are not allowed to take, a greyed-out control in one module and a control that is simply absent in another. Both are defensible. Having both is not, and it is the kind of decision that should be a one-line rule written before the first screen.
I would also have pushed for usage data on the admin side sooner. On the founder side we could argue from interviews. On the admin side the honest signal is whether an organization is still building courses and running reviews six weeks after onboarding, and that is a number I wanted and did not have.
