skip to content
[··]nano-os v7.0 — booting portfolio
revival nano adolor
senior frontend engineer
00%
← work/02Kwikpikinternal product▶ find it in play mode

Kwikpik Super-app

A delivery app rebuilt as a mini-app shell.

Three major versions of the customer delivery app — real-time ordering, live rider tracking, in-app chat — then restructured so finance, bill-payment and dispatch plug into a shared core as independent mini-apps.

role
Lead · mobile architecture
year
2024 — now
platform
iOS · Android
live
private
stack
React NativeExpoRedux ToolkitTanStack QuerySocket.IOHedera
Dispatch — send a parcel
Automations — active, paused and completed
Home — wallet, bills and automations
AppRegistry.register(finance)
registerReducer("dispatch", …)
EventBus.emit("wallet:updated")
socket ● rider.location 3s
3
major versions shipped
3
mini-apps on one shell
2
apps on one pnpm monorepo

$ ls ./screens

14 screens · scroll →
Home — wallet, bills and automations
Home — wallet, bills and automations
Dispatch — send a parcel
Dispatch — send a parcel
Automations — active, paused and completed
Automations — active, paused and completed
My automations — recurring airtime, power and TV
My automations — recurring airtime, power and TV
Automate a bill — pick what to pay
Automate a bill — pick what to pay
Review an automation before it runs
Review an automation before it runs
Bulk payment — payroll to 5 recipients
Bulk payment — payroll to 5 recipients
A recurring bulk payout, weekly
A recurring bulk payout, weekly
Bill payments — airtime, data, power, TV and more
Bill payments — airtime, data, power, TV and more
Electricity, with “automate this bill”
Electricity, with “automate this bill”
Asset split — pay one bill from NGN, USDT and BTC
Asset split — pay one bill from NGN, USDT and BTC
Confirm purchase
Confirm purchase
Bill paid
Bill paid
Transaction details, bill payments and a Hedera receive screen
Transaction details, bill payments and a Hedera receive screen

The problem

Kwikpik started as a delivery app. Then it grew a wallet. Then bill payments, transfers, payment automations. Each feature was bolted onto one navigation tree and one Redux store, so every release touched everything, and every new product team had to understand all of it.

What I built

Over three major versions I built and evolved the customer app — real-time ordering, live rider tracking over Socket.IO, in-app chat — and then restructured it into a mini-app shell.

  • An AppRegistry. Each mini-app (dispatch, finance, bill payment) is a self-contained folder that exports a config and registers itself. The shell lazy-loads them on boot.
  • Runtime reducer injection. Core slices (auth, user, UI) are always there; a mini-app's slices are registered when it loads, after persisted state rehydrates. Nothing in the core imports a mini-app.
  • An EventBus for the few things that do cross boundaries — wallet:updated after a transfer, for instance — instead of mini-apps reaching into each other's state.
  • Per-mini-app navigation. Each one owns its screen list. A config that tries to be both a root navigator and a tab is rejected at registration, not discovered in QA.
  • A shared kwikpik-ui package — tokens, typography, components — in a pnpm monorepo shared with the rider app.

Money movement

I built the wallet's money-movement suite and the payment automations on top of it: recurring bills, scheduled transfers, and bulk multi-recipient transfers with per-recipient status. Later I migrated the wallet from Flutterwave fiat rails to a custom Hedera Hashgraph wallet — the hardest kind of migration, because nobody notices when it works.

The rider app

The companion rider app handles last-mile delivery, including for Temu and other e-commerce platforms: accepting jobs, live location, wallet and KYC. I own its over-the-air releases and production stability — which mostly means saying no to shipping native changes through an OTA channel.

Outcome

  • New products ship as mini-apps without touching core navigation or the root store.
  • Two apps share one component library, so a design change is one PR, not two.
  • Three generations of the app, each one shipped without a rewrite freeze.
next case study →FinnaCrypto-native money: wallets, swaps, lending
✓