An operations portal for a UGC creator agency: a 14-step onboarding pipeline, campaign management and weekly posting tracking, on role-based access over a live Postgres.

Onboarding pipeline: 14 steps per creator per campaign, manual and auto cells

Weekly posting grid: Mon-Sun per creator with the Monday-target KPI

Campaign management: status, assigned creators and posting targets

Tier thresholds: min views and engagement rate for Bronze/Silver/Gold
// OVERVIEW
I built the operations side of a portal for a UGC creator agency. Coaches and admins run creators through onboarding, assign them to campaigns, and track whether each one posts on schedule. I worked full-stack across two milestones: the data model in Postgres, the API in Vercel Functions, and the React admin pages on top. The frontend is Vite + React 18 + TypeScript, data is Supabase with row-level security, and anything that needs a server key or a webhook signature runs in a Vercel Function under /api.
The core is a 14-step onboarding pipeline. Each creator moves through it once per campaign, and the steps close in different ways. Some an admin clicks through, some fire from a database trigger, and four close on their own from outside services. A signed contract in PandaDoc, a booked call in Cal.com, and a submitted draft each land on a webhook that matches the event back to the right creator and campaign and ticks the step off. The webhooks verify an HMAC-SHA256 signature before they write anything, and because neither PandaDoc nor Cal.com carries our campaign id, the receivers rebuild it from the document name or the assignment table.
The constraint that shaped everything was a live database with 315 real users from day one. Every migration is additive and idempotent, applied on a feature branch and merged by the client, so nothing I shipped could drop or rewrite existing data. Access is role-based in Postgres itself: admin, coach and member each get a different slice, enforced in RLS instead of the app layer. Where a member has to advance their own onboarding, like submitting social handles to close a step they can't write to directly, a SECURITY DEFINER trigger does it for them.
Over two weeks and 54 commits I shipped both milestones: the creator portal first, then the admin layer, which is campaign CRUD, a cross-project review queue, the Mon-Sun posting grid with a Monday KPI, a creator directory, tier thresholds and the pipeline table. It went to production for the agency's full roster.
// KEY FEATURES
Each creator moves through 14 steps once per campaign; some cells an admin clicks to cycle, some close from a database trigger, and four close automatically from outside services, with a dependency chain locked in the UI.
PandaDoc, Cal.com and draft-upload events hit Vercel Functions that check an HMAC-SHA256 signature, then reconstruct the campaign from the document name or assignment table since neither service carries our id, and close the matching step.
A Monday-to-Sunday grid per campaign pulls view counts from viral.app and flags whether each creator hit the Monday target, with a single org-wide pull matched to handles on our side to stay inside the rate limit.
Admin, coach and member each see a different slice, enforced in row-level security rather than the app; where a member advances their own onboarding, a SECURITY DEFINER trigger writes the step they can't touch directly.
12 additive, idempotent migrations shipped against a database with 315 real users, on a feature branch the client merged, so nothing dropped or rewrote existing data.
// RELATED WORK