ANONYMECODE&DESIGN
Back to InsightsDevelopment

Building a Marketplace for a Real Client

4 min read

Filivoire needed to be a real, live marketplace for crochet and handmade creations: genuine accounts, inventory synced across devices, and a payment flow able to eventually process real transactions. Not one more static catalogue.

One marketplace, four roles

React Native (Expo) + TypeScript, with Supabase as the backend (Postgres, Auth, Storage, Realtime). A single codebase covers four dedicated spaces, client, seller, courier and admin, across roughly 44 screens. Postgres Row Level Security policies determine who can read or write each table: a shop only ever sees its own verification documents, a courier only sees orders in its zone.

A few choices that matter in this kind of project:

  • The cart automatically splits into one order per shop when a client buys from multiple vendors, each with its own delivery fee.
  • The payment integration (GeniusPay) is validated end-to-end in test mode: payment, webhook, order creation, switchable to live mode with a simple admin toggle.
  • The seller/courier verification workflow (ID + business registration) is reviewed manually by the admin, with partner contracts generated automatically based on the commission rate.

Started on Firebase, migrated to Supabase

The project started on Firebase, then was fully migrated to Supabase mid-project, same features, no regressions, the day Firebase's new billing requirements became a blocker for the client's payment method. The payment integration itself went through more than one provider before settling on one whose verification tier matched the client's situation.

The real challenges

Getting real-time updates to actually propagate was the trickiest part: Supabase Realtime has to be explicitly enabled per table, and it fails silently if you forget. The initial load works fine, but live updates simply never arrive. Another trap: Postgres numeric columns serialize as strings by default over the API, which quietly breaks arithmetic on totals and ratings unless every money/rating column is cast to a floating-point type.

A lesson that goes beyond this project: test permission rules with a second real account, not just by reading the policy code. A subtle self-referential bug in an early access-control policy only showed up once tested from an actual second account, never from inspecting the SQL alone.

The result

A complete, working order flow, browse, cart split by shop, checkout, payment, seller fulfillment, courier delivery, admin oversight, running on a real backend and tested with the client through a shared app link. Real-money payment stays deliberately locked behind an admin switch while the client finishes onboarding with their payment provider.