All projects
CupidFaces Live

Ethliam

Quiet luxury e-commerce store for Nigeria: curated fashion, electronics, fragrance, and home goods with a full admin panel and Paystack checkout

180+
Orders fulfilled
300+
Registered customers
45+
Products in catalogue
Lagos, ships Nigeria-wide
Market
E-commerceNext.jsSupabaseNigeriaRetailAdmin Panel
Ethliam storefront
Storefront

The Problem

Nigeria's e-commerce market is dominated by discount-driven, high-volume platforms. The founder of Ethliam wanted to build something different: a curated store with honest Naira pricing, no flash sales, and a curation standard that kept the catalogue tight and intentional rather than growing into a generic everything-store.

Overview

Ethliam is a quiet luxury e-commerce store based in Lagos, shipping across Nigeria. The store's curation spans fashion, electronics, fragrance, and home goods, with every product personally reviewed before listing. Pricing is in Naira with no hidden conversion.

The platform is a full Next.js application backed by Supabase for the database, Cloudflare R2 for product image storage, and Paystack for Nigerian payment processing. It includes a customer-facing store with product pages, category browsing, a shopping bag, and checkout, plus an admin panel for product management, order tracking, and inventory.

My Role

  • Defined the product strategy and led full delivery: storefront, checkout, admin panel, and the Journal editorial section
  • Shaped the brand and curation policy: what gets listed, how products are described, and how the store communicates its quiet luxury positioning
  • Specified the pricing and payment model: honest NGN pricing, Paystack integration, and webhook-based order confirmation
  • Defined the image architecture: Cloudflare R2 for zero egress cost on a product-image-heavy catalogue
  • Designed the bag behaviour for both guest and authenticated users, including the merge strategy when a guest logs in mid-session
  • Specified the admin panel scope: product creation and editing, order management, inventory tracking, and draft/published workflow
  • As a solo-stage project with no separate engineering team, I contributed directly to development alongside product ownership.

Stakeholders

  • Ethliam founder (client)
  • End consumers in Lagos and across Nigeria
  • Paystack (payment partner)
  • Cloudflare (image delivery infrastructure)

Technical Context

Next.js App Router with Supabase for PostgreSQL and auth. Product images and journal covers are stored in Cloudflare R2. The admin panel is a protected route segment gated by the is_admin flag on the users table. Supabase Row Level Security handles data access policies at the database level.

Orders flow through Paystack: the checkout page creates a pending order in the database, initiates a Paystack transaction, and redirects the customer to Paystack's hosted payment page. On successful payment, a Paystack webhook hits the confirmation route which verifies the transaction reference and marks the order as paid.

Product prices are stored in kobo (the smallest Naira unit) to avoid floating point precision issues on payment amounts.

Key Decisions

Cloudflare R2 for image storage instead of Supabase Storage
R2 has zero egress fees on data served to end users, which matters for an image-heavy product catalogue.
Prices stored in kobo to avoid floating point issues
Storing in kobo as an integer means all arithmetic is exact. Paystack also accepts amounts in kobo, so there is no conversion needed when initiating a payment.
Webhook-based order confirmation rather than redirect-based
Relying on the redirect back from Paystack's payment page is fragile: the customer might close the tab before the redirect completes. Using webhooks means the order is confirmed by Paystack's server-to-server call, regardless of what the customer's browser does after payment.
Quiet luxury positioning as a product constraint, not just a design direction
Every product decision runs through the same filter: does this earn its place? That constraint keeps the catalogue tight and intentional rather than growing into a generic everything-store over time.

Challenges

Keeping the bag consistent for both guest and logged-in users
A logged-in user's bag lives in Supabase and persists across devices. A guest's bag lives in client-side state. When a guest logs in, their local bag needs to be merged with whatever is already in their Supabase cart.
Admin panel security on a public-facing Next.js app
The admin panel is a route segment within the same Next.js application as the public store. Keeping it secure means checking the is_admin flag on every admin route, not just at the layout level.

Discovery

The positioning came from the client, not from a research exercise. They had a clear instinct: the Nigerian market did not need another high-volume, discount-driven platform. "Quiet luxury" was the client's phrase from the first meeting. The product decision was to treat that as a curation constraint built into every decision.

Stakeholder Friction

The main stack question was whether to use Shopify or build a custom Next.js application. Shopify would have been faster to launch but would have imposed a generic visual language that conflicted directly with the brand positioning. The client chose the custom build specifically because full control over how the store looked and felt was non-negotiable.

Outcomes

180+ orders fulfilled with zero payment reconciliation failures
Over 180 orders processed with no payment confirmation failures. Webhook-based order confirmation eliminated the category of lost orders caused by customers closing the tab after paying.
300+ customers shopping a deliberately curated catalogue
300+ registered customers with a catalogue that has stayed tight at 45+ curated products. The curation constraint has held: the store has not drifted toward volume despite growth.
Zero image delivery cost at scale
Cloudflare R2 with zero egress fees means delivery cost for a product catalogue with multiple gallery images per listing has remained at zero regardless of monthly traffic volume.

Technology Decisions

Next.jsReact 19 + TypeScriptSupabase + RLSCloudflare R2PaystackTailwind CSSVercel

What I'd Change

A wishlist feature, from day one. A meaningful portion of customers browse, do not buy immediately, and come back. Without a wishlist, the only way to save a product is to add it to the bag and abandon it. It is a standard e-commerce feature that was deprioritised to get the core checkout flow right at launch.

From the blog

All posts
The Real Skills You Need as a Technical Product Manager
There’s a lot of confusion about what a Technical Product Manager actually does.
22 May 2026
JobHunt: What I Was Actually Trying to Fix
Most of the products I build start with a small, persistent frustration. Something I've experienced myself or watched someone close to me struggle with and couldn't stop thinking about.
17 May 2026
ProductManagement
Building JobHunt: A TPM's Notes on Shipping an AI Job Application Assistant
I'm a Technical Product Manager. I think in user journeys, prioritisation frameworks, and edge cases. What I don't usually do is write the code. JobHunt changed that, not because I suddenly became a software engineer, but because AI-assisted development has made the distance between an idea and a working product smaller than I've ever seen it. This is a record of what I built, why I built it that way, and what the decisions looked like in practice.
17 May 2026
← PrevFalkOne GS LtdCupidFacesNext →PM NotifierVisibility Logic
Ethliam: Quiet luxury e-commerce store for Nigeria: curated fashion, | Nicholas Olaniyi