Skip to content
Back to work

Entertainment & event platform

VotArena

Event platform for French-speaking Africa: paid-vote competitions with a live public leaderboard, QR ticketing delivered on WhatsApp and organizer payouts, all paid by Mobile Money. Designed, built and operated by one engineer, live since March 2026 with verifiable early traction.

Client
Own product — Fingers Technologies
Role
Founder, CEO & CTO — sole engineer
Period
March 2026 – present
Status
In production
VotArena home screen: crown logo, animated phone mockup and the "Start" call to action
VotArena home screen: crown logo, animated phone mockup and the "Start" call to action
Home
VotArena competitions feed: a paid-vote competition with its vote and engagement counters (figures blurred)
Competitions feed (figures blurred)
VotArena events feed: an event card with date, venue and ticket price
Events feed
VotArena sign-in screen: WhatsApp one-tap sign-in as an alternative to a password
Sign-in (WhatsApp)

The problem

Competitions in Cameroon — pageants, talent contests, galas — sell paid support, but the count is opaque. Votes are tallied in a notebook or a spreadsheet, and the money lands on someone's personal phone number with no receipt. When a result is disputed, the organizer has no proof to show and buyers have no reason to trust the next edition.

Existing ticketing tools cover tickets only. None of them combines votes, tickets, registrations, partner stands and artist sales on one account, publishes its revenue split, or verifies each event before it goes on sale. Mobile Money is the dominant payment method, and the two main operators in Cameroon are reached through different providers with different constraints.

The engineering constraint followed from the product: the platform had to accept real money from the first day, on 3G connections and 360 px screens, with one engineer to build it, run it and answer support.

The product

VotArena runs four product lines on one codebase. Paid-vote competitions: votes paid by Mobile Money, a live ranking, voting sessions with eliminations and a WhatsApp campaign kit per candidate. Ticketing: a QR ticket and a 5-character code delivered on WhatsApp, guest checkout without an account, an approver role per event and a ticket that can be burned exactly once at the door. An artist space with music sales, merchandise, tours and an opt-in fan list, plus paid registrations and partner stands.

The common base is an installable PWA in French and English with passwordless login through a WhatsApp number. Payments go through NOKASH for MTN and Orange Cameroon and through Tara Money for other operators, other countries, cards and payment links. Organizers see their balance and request withdrawals, which are paid out to their Mobile Money number.

The back office covers super-admin, moderation, support with logged searches, payment case tracking shared between admins and organizers, withdrawal approval and an append-only audit log of admin actions. The commission model is published: 20% on votes, 10% on tickets, 15% on music, 10% on the shop, 0% on registrations and stands.

My role

I founded VotArena and lead it as CEO and CTO under Fingers Technologies. I am the sole engineer: all 457 commits between 14 March and 25 September 2026 are mine, from product specifications and architecture to code, tests, deployment, monitoring and support.

Outside the code, I wrote the organizer contracts, the pricing and the pitch deck, and I coordinate the commercial, finance and legal work.

The challenges

  1. Routing each Mobile Money payment to the right provider without asking the user

    The problem

    NOKASH requires the operator (MTN or Orange) up front and rejects amounts under 200 XAF. Tara Money accepts everything and detects the operator itself, but costs more per transaction. Asking a buyer which operator they use at the moment of a 100 XAF vote loses the sale.

    What I built

    A PaymentRouter behind a port derives the Cameroonian operator from the phone number prefix, sends MTN and Orange to NOKASH and everything else — other countries, Wave, sub-minimum amounts — to Tara. A MobileMoneyGateway normalises initiation so the vote use case never knows which provider handles it. Ticketing uses a NOKASH-only route with no fallback.

  2. Making every franc traceable without ever failing a real payment

    The problem

    Organizers and admins need to know where each payment stands: initiated, confirmed by the provider, credited, paid out. But a failure in logging or projection must never block a customer who is paying.

    What I built

    An append-only PaymentEvent journal with a best-effort contract: implementations swallow their own errors and report them to Sentry. A decorator on the port projects each event into a PaymentCase (customer, WhatsApp number, tickets, event) within a 2.5-second budget, and a batch rebuild use case replays the journal to catch up any missed projection. Admin actions are logged under the same contract.

  3. Organizer payouts without double disbursement — and without database transactions

    The problem

    Payouts go through the NOKASH disbursement API. A lost callback froze a request, a PENDING callback was treated as a failure, and two admins clicking Approve could pay the same request twice. The hosting plan runs the cron once a day, so reconciliation cannot rely on it alone.

    What I built

    A WithdrawalRequest state machine persisted with conditional writes: each update is filtered on the status, payout reference and phone number previously read, checks that exactly one document matched, and never upserts. There are no MongoDB transactions in the codebase; atomicity comes from conditional updates and unique indexes. Status sync runs opportunistically when the admin queue refreshes, a daily cron catches the rest, and PENDING callbacks are acknowledged without failing the request.

  4. Passwordless login through WhatsApp after Meta rejected the outbound template

    The problem

    The plan was to send a login code by WhatsApp. Meta rejected the Utility template carrying the code: outgoing codes are reserved for the Authentication category, available to verified businesses. The product still needed a login with no password and no email.

    What I built

    The flow was inverted: the user sends a short confirmation message through a wa.me link, and the signed Meta webhook attributes the action to the sender number attested by WhatsApp. The same gesture confirms a number, signs in and creates an account. An outbound OTP path with peppered codes, time windows and attempt caps is ready for when Authentication templates are approved.

  5. Per-use-case observability that does not take the API down

    The problem

    Turbopack builds do not get Sentry's build-time auto-instrumentation, so use cases had to be instrumented by hand. A first attempt wrapped every entry of the dependency container in a Proxy, including a boolean, and took the whole API down on 24 September 2026.

    What I built

    One instrumentation point: at container build time, a generic function wraps once every entry that passes a type guard on its execute method in a Proxy that opens a use-case span and captures exceptions. Repositories get the same treatment. PII scrubbing is centralised and default PII sending is off. The type guard is what prevents a repeat of the outage.

The outcome

Paid votes
3,472381,920 XAF, one competition
Ticket orders
52259,242 XAF confirmed
Organizer payouts paid
22466,352 XAF
User accounts
214
Automated tests
6,087all passing, 25 September 2026

as of 23 September 2026

VotArena is live on votarena.com and takes real payments. Read from the production database on 23 September 2026: 3,472 paid votes (381,920 XAF), all from one competition run in March and April 2026; 52 confirmed ticket orders (259,242 XAF); 22 organizer payouts actually paid (466,352 XAF); 214 user accounts. The pitch deck of 3 September 2026 counted 5 organizers.

These are early figures, not a growth story: field sales are only starting. What they show is a payment path that works end to end — vote or ticket purchase, provider callback, organizer balance, payout — with an audit trail at each step.

On the engineering side: about 120,000 lines of TypeScript excluding tests, 32 domain sub-areas, 46 ports, 228 use cases, 188 API routes, 62 pages and 3,596 translation keys in French and English. The suite run on 25 September 2026 executes 6,087 tests across 1,843 suites, all passing; a test campaign in July 2026 surfaced 15 production bugs, all fixed. An Android app (TWA) is built but not on the Play Store yet.

Technical stack

Frontend
  • Next.js 16 (App Router)
  • React 19
  • TypeScript 5 strict
  • Tailwind CSS 4 + shadcn/ui
  • next-intl 4 (FR/EN)
  • SWR
  • Installable PWA (service worker, web manifest)
Backend & architecture
  • Next.js Route Handlers (188 API routes)
  • Hexagonal architecture: domain, ports, application, infrastructure, presentation
  • Typed dependency container
  • Result<T, E> for business errors instead of exceptions
  • zod 4 validation
  • next-auth v5
Data
  • MongoDB Atlas via Mongoose 9 (44 schemas, 42 repositories)
  • Conditional updates and unique indexes (no transactions)
  • Redis fail-open cache
  • Cloudinary (images, signed audio URLs)
Payments & messaging
  • NOKASH (MTN and Orange Cameroon pay-in, organizer payouts)
  • Tara Money (other operators and countries, cards, payment links)
  • Webhooks authenticated with constant-time comparison
  • WhatsApp Cloud API (ticket delivery, signed inbound webhook)
Infrastructure & observability
  • Vercel (hosting, daily cron)
  • Sentry (use-case spans, PII scrubbing, tunnel)
  • docker-compose for local development
  • Android TWA built with Bubblewrap
Testing & tooling
  • Vitest 4 + jsdom: 6,087 tests, 1,843 suites
  • Pre-commit hook running the suite
  • ESLint 9 + Prettier
  • Translation catalog alignment test