Skip to content
Newman Adesan
All work

Multi-service ordering and delivery marketplace

Swyftng

I have built Swyftng's web platform since the MVP in May 2024, through five major versions. Version 5 has just shipped.

Role
Frontend developer
Period
May 2024 – present
Live
swyftng.com
Tools

Tools used: React, TypeScript, Vite, React Query, Zustand, React Hook Form, Zod, Tailwind CSS

Admin: gift card colour themes, with how many cards use each
Admin: gift card colour themes, with how many cards use each
Supermarket storefront with category filters
Supermarket storefront with category filters

The problem

Swyftng lets customers order from restaurants, supermarkets, local markets and home care services in one place, book a rider for any parcel, and pay with gift cards and earned credit. Vendors, riders and Swyftng's own staff run their side of each order, and the platform has grown by a new kind of order with almost every version.

What I built

  • Consumer, vendor, rider and admin interfaces in one React app.
  • The full order workflow, from payment through processing to delivered, for every kind of order the platform sells.
  • Credit and rewards end to end: gift cards, referrals, feedback rewards, cashback and special packages, from the customer's wallet to the admin tools that manage and track them.
  • Cursor pagination on the credit management tables, using the pattern I first designed on the ambulance platform.

Five versions, one codebase

  1. v1Food ordering and delivery, with consumer, vendor, rider and admin interfaces.
  2. v2Errands from supermarkets, local markets and drink shops, fulfilled by Swyftng's own marketers.
  3. v3Swyftng Express+: book a dispatch rider for any parcel.
  4. v4Personal and home care services, booked as appointments.
  5. v5Credit management (gift cards, referrals, cashback and feedback rewards) and special packages.

One app, every interface

Swyftng serves customers, vendors, riders and admins from one React application.

Each interface has its own layout, routes and context, and they share one onboarding flow that signs a user in and sends them to the right interface for their role. A session that lands in the wrong interface is signed out rather than shown someone else's screens. Marketers are Swyftng staff who shop the errands customers order, and they work from a separate mobile app. My side of that is where it meets the web: the customer placing the errand, and the admin seeing and managing the marketer's orders alongside every other kind. Shared building blocks live in one place: the API client, the query hooks and the UI kit. A fix to how errors are handled reaches every interface at once.

Growing through five versions without a rewrite

Almost every version added a new kind of order: restaurant meals, market errands, parcel dispatch, home care appointments, gift cards, then special packages.

Each one touches the cart, checkout, order history and the admin. Rewriting for each was never an option on a live platform, so the work was making every layer accept a new order type without breaking the old ones. The customer's order history card works out which kind of order it is showing and renders the right details, prices and actions. The admin's order view does the same, and product management handles restaurant, market, service and special-package products, each with its own create and edit rules. By v5 checkout had grown into one 1,672-line component, plus a separate guest cart and two toast libraries. I rebuilt it as a three-screen wizard (cart, checkout, then transaction PIN) driven by a single order context that owns the cart query, the delivery and payment choices and every mutation. If the customer has no PIN yet, creating one is its own small state machine: create, confirm, verify by OTP, then enter. Redeeming a gift card and applying earned credit then went in as one component each.

Admin roles, permissions and an audit trail

The super admin invites other admins, creates roles from any set of permissions, assigns a role to each admin, and can suspend or restore an account.

The admin list shows who is online, who is offline, when each admin last signed in, and who has been invited but hasn't joined yet. Every change an admin makes is recorded: who made it, which record it touched, and the old and new value of each field. A product's price, discount or approval status can be traced to the person who changed it and when, and each admin's account page lists their recent actions.

A colour system admins can't break

Admins design gift cards and special-package cards themselves, so colour had to be safe in their hands.

A gift card's design is four colours. I curated 30 named combinations that work together, and the backend stores only the four hex values. The names live only in the frontend, so they can be renamed without touching the API. When an admin picks a theme, each option shows whether it is already in use and on how many cards. When an admin edits a card, the right theme is pre-selected by matching the stored colours back to a name. A special package needs only one colour. The card's grid lines are derived from it, same hue and slightly darker, so no choice can clash. The card works in HSL internally and converts to hex only at the API boundary, and it still reads an older colour format the backend once stored, so old packages keep rendering.

Try it· Design a gift card
₦20,000Gift Card
Birthday treat

SUPA · in use on 2 cards

Colour
Value

What the API receives

{
  "name": "Birthday treat",
  "value": 20000,
  "design": {
    "colors": {
      "primary": "#EDDEE3",
      "secondary": "#F6EFF1",
      "accent": "#850E35",
      "text": "#850E35"
    }
  }
}

Only the four colours are stored. When this card is opened for editing, they match back to SUPA, so the picker pre-selects it.

The card component and its 30 themes are ported from Swyftng's admin. Nothing is sent anywhere: the request body is shown, not posted, and the usage counts start from sample data.

When the data disagrees

In a customer's order history, expanding a special-package order showed the wrong price for its items: ₦1,500 where the customer had paid ₦15,000.

The screen was reading the product's base price. The backend sends several price fields for each cart item, and they don't agree: one is sometimes a spurious 0, and the base price ignores the variation the customer chose. Instead of guessing which field to trust, I checked each one against 100 real orders and counted where the line totals added up to what was charged. Regular products reconciled best on the product price, dynamic packages on the selected variation's price, and static packages on the base price. I reordered the fallback chain to match. That fixed 5 orders with no regressions. Two orders matched no combination of fields at all. I sent them to the backend team with the evidence, because the real fix is one authoritative charged price per item. Until then, my chain is a documented workaround.

Breadcrumbs that follow the admin anywhere

Admins investigating a problem jump between records: from an order to the customer who placed it, to the vendor, to one of the vendor's products, and back.

I built each detail view (order, account, business, product, service) as a self-contained component that takes the breadcrumb trail it was opened from, adds its own crumb, and passes the longer trail to whatever it opens next. Because every view works the same way, they nest in any order and work from any admin section, and clicking any crumb returns to that level. The trade-off is that the trail lives in component state rather than the URL, so a page refresh returns to the list. Moving it into the URL is the next step.

Swyftng landing page
Swyftng landing page
Restaurant listing with sort options
Restaurant listing with sort options
Search results grouped by service
Search results grouped by service
Gift card store for customers
Gift card store for customers
Customer credit balances: referral, gift card, feedback, cashback
Customer credit balances: referral, gift card, feedback, cashback
Admin: active gift card templates
Admin: active gift card templates
Admin: editing a special package
Admin: editing a special package
Admin: processing and delivery fees per service
Admin: processing and delivery fees per service
The Swyftng landing page