Full-stack buildReact NativeSupabase

Dues, end to end.

A dues and payments app for a private members club, built solo as a freelance project. A React Native front end, a Supabase backend for roughly 460 members (Postgres, row-level security, edge functions), and a real payment gateway. Designed and coded end to end.

The club paused the rollout before launch, so this is a build, not a shipped product. The decisions were real. So was the money.

Role: Sole designer and developer (freelance)·Scope: Research to payments·Stack: React Native, Supabase, AvalPay·Status: Feature complete


The build

Everything ran by hand.

A private members club still ran its billing the way it always had. Dues varied by membership tier. On top of dues, each member owed a monthly minimum spend at the restaurant, charged as the gap between the minimum and what they actually spent. All of it lived in an ERP, reconciled by hand. Members had no way to see their balance or pay without walking into the office.

I built the app that closed that gap, alone, from the first research call to the payment gateway.

Home — dues status
Payment — gateway methods
History — invoices by year

The constraint

Built for members aged 40 to 70.

That single fact drove the type sizes, the contrast, the tap targets, and how restrained the motion is. Every animation sits behind a reduced-motion check. The constraint came from the people, not from a checklist.


The decision that mattered

The revenue report that would have quietly broken.

Halfway through, the club switched payment providers, from Wompi to AvalPay. The migration plan was simple: stop writing to the old payments table, write to the new flow instead.

Before deleting the write, I traced who still read that table. The admin dashboard did. It built the club's revenue statistics from it.

Stopping the write would not have thrown an error. It would have silently erased every AvalPay payment from the reports the club used to see its own money. The kind of bug nobody notices until the numbers are wrong at the end of the month.

Payment architecture: the payment flow writes to the payments table, and the admin dashboard reads its revenue stats from the same table.

The fix was not to keep the write blindly. It was to keep it only after the payment was confirmed server-side, and to add an idempotency guard, because a status check can legitimately return approved more than once. The report stays whole, and it never double counts.

The most dangerous bugs never throw an error.


Status

Certified, then shelved.

Feature complete. Payments certified into the gateway's sandbox. Then the club decided not to roll it out, and no member ever used it.

I am keeping it here anyway, because a build is not only what ships. It is the decisions you make when the money is real and no one is watching the code but you.


More work

Back to the rest of the work

Return home