Fanflo
NIL deals between athletes, schools and brands
- State
- Status: Live
- Role
- Lead developer
- Year
- 2024
- Stack
- Laravel
- Vue
- MySQL
A platform for US college sports name, image and likeness arrangements. Athlete claim flow, KYC on the payout path, compliance reporting, and a stateful refund workflow, with tenant isolation across three different party types.
The problem
Name, image and likeness deals put money between three parties who each answer to a different rulebook: the athlete, their school's compliance office, and the brand. Every one of them needs a different view of the same transaction, and the money cannot move until identity is established. Getting that wrong is not a bug report, it is an eligibility problem for a student athlete.
Constraints
- Identity verification is mandatory before any payout, and the verification provider is asynchronous.
- Three party types with genuinely different permission shapes, sharing one transaction record.
- Refunds have to be auditable and reportable, not a one-click reversal.
Architecture
A Laravel application where the deal is the central record and athletes, schools and brands are separate tenant types with their own policy surfaces over it. Verification sits as a gate on the payout path rather than at signup. Refunds are modelled as a workflow with explicit states so that every transition is recorded and reportable.
Decisions and what they cost
Gate KYC on the payout path, not on registration.
- Why
- An athlete asked to complete identity verification before they have seen a single offer will not complete it. Blocking at the money boundary means the funnel stays open and verification happens at the point where the user has a reason to finish it.
- What it cost
- Partially verified accounts exist throughout the system, so every path that can move money has to check verification state independently. The check cannot live in one middleware.
Model athlete, school and brand as distinct tenant types rather than one generic organisation.
- Why
- Their permissions are not variations of each other. A school sees compliance data on athletes it does not employ; a brand sees commercial terms it cannot see for other brands; an athlete sees their own money. Collapsing that into one org type with a role flag produces policy code full of special cases.
- What it cost
- More policy code and more surface to test, because each type needs its own authorisation coverage rather than sharing one.
Implement refunds as a state machine, not a single action.
- Why
- A refund touches the athlete's balance, the brand's invoice and the school's compliance record. Those do not settle at the same instant, and a refund that half-applied with no recorded state is unresolvable.
- What it cost
- A refund is now several steps with intermediate states that support staff have to understand, rather than a button.
What it does
Athlete claim flow
An athlete claims their own profile against records the platform already holds, so the deal surface is populated before the athlete has to type anything.
Verification as a money-path gate
Identity checks run asynchronously and block payout rather than access, keeping the top of the funnel open without letting unverified money move.
Three-party tenancy
Athletes, schools and brands read the same deal record through three different policy surfaces, each scoped to what that party is entitled to see.
Stateful refunds
Reversals move through recorded states across balance, invoicing and compliance, so a partially applied refund is a known position rather than a mystery.
