Frank Fontcha.
← All work

Product · 2024 — Present

MboaMeet

Social and creator-commerce platform with encrypted chat, calls, lives and an HLS video feed.

MboaMeet is a social and creator-commerce platform. People follow creators, chat, call, join lives, run channel stores and buy from each other in chat. I architected and built all of it: the Expo app, the .NET 10 modular-monolith API (about 20 modules), the Next.js web client, the AI studio service and the infrastructure.

Visit mboameet.com ↗
MboaMeet community feedMboaMeet chats and channelsMboaMeet in-chat deal with a seller

Architecture

  • ASP.NET Core modular monolith: Calls, Chats, Feeds, Lives, Groups, Stores, Wallets, Studio and more, each split into Api, Data and Services.
  • Real time: SignalR hub for chat, presence and call signalling, with user-to-connection maps in Redis.
  • Media: react-native-webrtc + coturn for P2P calls, self-hosted LiveKit SFU for lives and call fallback, and an FFmpeg HLS ladder on Hangfire served by Nginx.
  • Payments: RevenueCat subscriptions and token packs through an idempotent webhook inbox, Stripe PaymentIntents and mobile money for wallet top-ups.
  • AI Studio: a Django service in front of Gemini image editing and Lyria music, billed in tokens with automatic refunds when a generation fails.
  • CI/CD: GitHub Actions build and test, then an SSH deploy that runs Docker Compose.

Flows I’ve written up

How specific parts of MboaMeet work under the hood, with code you can reuse.

4 Oct 20266 min read

A write-behind view counter with two Lua scripts and one Postgres UPDATE

Counting video views with one UPDATE per view turns your hottest table into a lock queue. Here's how MboaMeet dedupes views in Redis with a single Lua round trip, buffers them in a hash, and flushes them to Postgres every five minutes in one statement, plus the failure mode I accepted and how I'd remove it.

RedisLuaPostgreSQLASP.NET Core
5 Sept 20269 min read

A payment webhook inbox that can't double-credit: RevenueCat, Stripe top-ups and an AI billing saga

Payment providers retry webhooks, deliver them out of order and sometimes send the same event twice, and every one of those cases can turn into free tokens or a lost purchase. Here's the inbox pattern I use in MboaMeet: store the raw event under a unique id, process it later from a background worker, and make every credit and refund idempotent by reference.

ASP.NET CorePostgreSQLPaymentsWebhooks
22 Aug 20269 min read

An HLS video ladder on a single VPS: H.264 + HEVC tiers, aligned keyframes and Nginx doing the serving

A scrolling video feed needs fast starts and small files, and a CDN-backed media pipeline is a lot of infrastructure for an early product. Here's the pipeline I built for MboaMeet's feed: client-side compression, a Hangfire + FFmpeg ladder with three tiers in two codecs, and Nginx serving the segments straight from disk.

FFmpegHLSVideoHangfire
30 Jul 20269 min read

P2P-first 1:1 calls that fall back to an SFU mid-call without hanging up

Peer-to-peer WebRTC is cheap and private until a carrier NAT breaks it, and an SFU always connects but costs server bandwidth on every call. Here's how MboaMeet starts calls P2P with Coturn, and switches both phones to a self-hosted LiveKit room on the same call id when ICE fails.

WebRTCReact NativeSignalRLiveKit
8 Jul 202611 min read

Incoming calls that ring when the app is dead: VoIP push, CallKit and data-only FCM in React Native

A calling app is only as good as its ring, and a ring that needs a live WebSocket fails the moment iOS or Android kills your process. Here's the push-only pipeline I built for MboaMeet: PushKit reported to CallKit in native Swift before JavaScript boots, data-only FCM on Android, and a server that routes each token to the right transport.

React NativeiOSCallKitPushKit