Back to Project
FintechPrivate-safe case study

XcroPay Technical Case Study

A full-stack escrow platform for Nigerian commerce, built as a TypeScript monorepo spanning a public site, admin portal, Express/Supabase API, shared validation package, and Expo mobile app. The core engineering challenge was turning trust-heavy buyer/seller commerce into auditable state transitions, verified money movement, and recoverable operational workflows.

Tech At A Glance

TypeScriptTurborepoExpress 5SupabaseNext.jsExpoReact NativePaystackQoreIDSendGridTermiiFirebase FCM

Surfaces

Web · Admin · API · Mobile

API Shape

14 route files / 100+ handlers

Database

35 Supabase migrations

Test Surface

24 API/shared test files

Why It Matters To Recruiters

  • Owned a multi-surface fintech build across web, mobile, admin, API, database, and shared packages.
  • Modeled escrow as a state machine instead of scattering transaction rules across UI handlers.
  • Kept money movement server-side with payment verification, webhook reconciliation, and admin-gated exceptions.
  • Used shared TypeScript/Zod contracts so API, admin, and mobile surfaces agree on request shapes and domain enums.
  • Designed operational tooling for launch readiness: audit trails, exports, admin actions, queues, and provider health checks.

Platform Surfaces

Consumer Web

Next.js public site with launch pages, legal/content pages, CMS-backed fallbacks, and security-conscious deployment defaults.

Mobile App

Expo Router app for buyer/seller flows: onboarding, KYC, transaction creation, delivery proof, disputes, messaging, ratings, and notifications.

Backend API

Express 5 service with route/controller/service layering, shared Zod validation, Supabase data access, payment webhooks, and internal jobs.

Admin Operations

Separate Next.js admin portal for support workflows, dispute review, merchant oversight, reporting, role controls, and audit trails.

Problem

Informal online commerce creates risk on both sides: buyers worry about paying before delivery, sellers worry about releasing goods before funds are secured, and operators need a defensible way to settle disputes. XcroPay solves that with an escrow workflow that holds funds, records evidence, verifies identity, and keeps every sensitive transition auditable.

Architecture

  • pnpm/Turborepo workspace separates `apps/web`, `apps/admin`, `apps/api`, `apps/mobile`, and `packages/shared` while sharing strict TypeScript contracts.
  • API routes stay thin: middleware handles auth/rate limits/validation, controllers translate HTTP requests, and services own escrow business logic.
  • Supabase stores users, KYC records, bank accounts, transactions, disputes, evidence, messages, ratings, notifications, admin actions, and operational queues.
  • The transaction lifecycle is represented as allowed transitions: created, accepted, funded, delivered, inspection, completed, disputed, resolved, cancelled, and refunded.
  • Webhook events are queued with idempotency keys, claimed by workers, retried with backoff, and dispatched to provider-specific handlers.
  • Notifications are written in-app immediately and fanned out through an outbox for push, email, and SMS delivery without blocking the main request path.

Escrow Workflow

Step 1

Buyer creates a transaction with terms, category, seller invite, amount, fee, and inspection window.

Step 2

Seller accepts the invite, which locks the counterparties before funding can begin.

Step 3

Buyer funds escrow through a payment provider; the API verifies the charge before moving the transaction to funded.

Step 4

Seller marks delivery and uploads proof; the system moves the transaction into buyer inspection.

Step 5

Buyer confirms, disputes, or lets the inspection window expire; completion triggers payout, while disputes enter evidence review.

Step 6

Admin-only resolution paths support release, refund, split outcomes, and audit-logged force actions when manual intervention is required.

Key Engineering Highlights

  • Implemented kobo-only money math and fee helpers to avoid floating-point currency errors.
  • Added conditional transaction updates so stale clients or competing webhooks cannot silently overwrite state.
  • Built Paystack charge, transfer, refund, bank, and webhook wrappers behind service-layer orchestration.
  • Added QoreID identity checks for BVN/NIN verification while storing only hashed identity references in app tables.
  • Created file upload and signed URL flows for delivery proof, dispute evidence, profile assets, and private storage buckets.
  • Added export paths, pagination helpers, reference generation, structured API responses, and typed error classes for a consistent backend contract.

Security & Privacy

  • Row Level Security policies protect participant-scoped records at the database layer.
  • Supabase JWT verification is paired with app-level profile checks, session revocation, and protected admin cookies.
  • Admin-sensitive actions require role/permission checks, fresh MFA step-up, CSRF protection for cookie sessions, and audit logging.
  • Rate limits are backed by database counters so throttling works across multiple API instances.
  • Webhook handlers verify provider signatures before queueing work and ignore duplicate deliveries through idempotency keys.
  • Portfolio copy intentionally omits repository access, credentials, provider configuration, customer data, and internal handoff details.

Product Evidence

The public-facing website is shown here because the source repository is closed. Screenshots are safe to share and demonstrate the product positioning, visual system, and escrow-first user education.

XcroPay public website in light mode.
Public website hero: escrow positioning, buyer/seller trust framing, and launch messaging.
XcroPay public website in dark mode.
Dark-mode surface: same trust narrative with a fintech-oriented visual system.

Trade-offs

  • Chose a modular monorepo over separate repositories so shared domain contracts could evolve quickly during buildout.
  • Used Supabase for database, auth, realtime, and storage to reduce early operational burden while still enforcing RLS and migrations.
  • Kept the API as a well-layered service rather than splitting microservices before the transaction model stabilized.
  • Introduced durable queue tables for webhook and notification processing instead of relying only on in-memory side effects.
  • Separated the admin portal from the consumer app to keep operational controls behind stricter auth, permissions, and UI patterns.

Private-Safe Source Material

This case study is intentionally summarized for hiring review. It communicates engineering depth without exposing credentials, implementation-sensitive runbooks, customer data, financial terms, or private repository access.

  • Private XcroPay monorepo structure and package manifests.
  • API documentation, launch-readiness notes, and backend integration notes.
  • Shared schema/constants package, route definitions, migrations, and service-layer implementation.
  • Existing portfolio XcroPay project copy and public website screenshots.