Overview

A working storefront where customers personalise a product and see it before they buy, and alongside it the audit that found what stood between this and taking real money. The customiser, catalogue and cart run today; the payments and authentication work is specified decision by decision, ready to build.

The storefront: custom apparel and branded merchandise, built around the customiser.
The storefront: custom apparel and branded merchandise, built around the customiser.
Client
Branded merchandise retailer, Ghana
Industry
Retail & e-commerce

The challenge

  • Customers needed to see their own text and artwork on the product before ordering; a picture of a blank t-shirt sells nothing.
  • Checkout existed in the frontend but never charged, so the shop could not complete a sale.
  • Mobile money is how Ghana pays. Card is secondary, so leading with card in the UI would mean leading with the minority rail.
  • A security review found no email verification, no password reset, no MFA, no session revocation, and an admin account hard-coded in the repository.

Approach

The customiser: live preview of the product with your own text, font, weight, scale and rotation, before anything is added to the cart.
The customiser: live preview of the product with your own text, font, weight, scale and rotation, before anything is added to the cart.
  1. 01

    Build the customiser first

    The product page is a live preview: type your text, pick the font and weight, scale and rotate the artwork on the garment, then add the configured item to the cart. It is the part of the shop that does the selling, so it shipped first.

  2. 02

    Fail to boot rather than run insecure

    The API refuses to start when required secrets are missing, naming each one. An environment without signing keys can no longer come up quietly and issue tokens; the failure is loud, at boot, in every environment.

  3. 03

    Decide the payment rails before writing them

    A locked decision log fixes Paystack with mobile money as the primary path, card second, GHS only, money stored as bigint minor units, guest checkout with an account claimable later by email, and the failure modes to design for: 3G dropping mid-payment, a double-tapped pay button, a webhook arriving before the redirect. Providers sit behind one interface so a second gateway is an implementation, not a rewrite.

  4. 04

    Plan the data move once

    Managed Supabase Postgres alongside the object storage already in use, giving one vendor, one bill, daily backups and point-in-time recovery, with the schema drafted as migrations: uuid keys, timestamptz throughout, integer money, and line-item snapshots so order history survives catalogue edits.

What shipped

Live

product customiser: text, font, scale and rotation on the garment

Boot-time

hard-fail on missing secrets, in every environment

2

locked PRDs for payments and auth hardening, ready to build

Next

Paystack mobile money, Postgres cutover, TOTP for admins

Stack

  • Next.js 15
  • React 19
  • Express
  • TypeScript
  • Sequelize
  • PostgreSQL (planned)
  • Paystack (planned)
  • Railway