Knowledge Mark G
Hire Me

B2C e-commerce · live since Feb 2025

Online Pharmacy
and Healthcare Commerce Platform

A UK health, beauty and care storefront with a built-in pharmacy compliance gate.

A healthcare and pharmacy commerce platform powering two separate UK storefronts from one codebase: ASP.NET Core with clean architecture and CQRS behind a Next.js 15 storefront and admin panel.

Orders fulfilled
23,000+
Customer accounts
17,000+
Shipments dispatched
11,500+
Products
3,300+

Live Since 2025

23,000+ orders

01Summary

A full-stack e-commerce platform for a UK health, beauty and care retailer. Beyond the storefront it runs a pharmacy-style compliance gate for restricted over-the-counter products, Subscribe & Save, a loyalty-points engine, click & collect across physical stores, and a WooCommerce-compatible API so external fulfilment tools can read live orders.

  • Compliant checkout
  • Subscriptions & loyalty
  • Live Stripe payments
Online Pharmacy and Healthcare Commerce Platform

02The Problem

A retailer selling everyday products alongside pharmacy-restricted lines cannot run on a generic storefront template:

  • Some products legally require medical-suitability questions before checkout — without slowing down every other order.

  • Delivery mixes courier home delivery with click & collect, each with its own status lifecycle and ID capture at pickup.

  • Trustpilot's own invite system was rate-limited on the free tier and triggered at the wrong point in the order.

  • Third-party fulfilment tools built for the WooCommerce API needed live order data without the business running WooCommerce.

03My Role & Scope

End-to-end development, from architecture to deployment and ongoing production support.

  • Storefront & checkoutNext.js 15 storefront — catalogue, cart, multi-step checkout, Subscribe & Save, loyalty redemption, coupons and BOGO, Stripe and PayPal.
  • Pharmacy compliance gatePer-product question sets, responses captured at checkout, and a staff verification queue with approve/reject and a full audit trail.
  • Admin back officeNext.js console for orders, products, per-page RBAC, discounts, blog, banners, shipping and loyalty configuration, and a Google Merchant feed.
  • Backend APIASP.NET Core 8, Clean Architecture with MediatR CQRS, 43 controllers and background services for cart recovery, renewals, points expiry and email retry.
  • IntegrationsStripe, PayPal, Royal Mail postcode lookup, Evri tracking, Trustpilot automation, Google Merchant Center and a WooCommerce-compatible read API.

04Architecture

Alongside: a Next.js admin console, a WooCommerce-shaped read layer over live orders, and Trustpilot plus self-hosted post-delivery review emails. 108 EF Core migrations across about 24 feature areas.

  1. Customer storefront

    • Next.js 15
    • Catalogue
    • Cart
    • Checkout
    • Subscriptions
    • Loyalty
  2. ASP.NET Core 8 API

    • 43 controllers
    • Orders
    • Products
    • Pharmacy
    • Shipping
    • Payments
  3. Application layer

    • MediatR CQRS
    • Commands
    • Queries and validators
  4. Infrastructure

    • EF Core / SQL Server
    • Background services
    • Email templating with retry
    • Stripe/PayPal
    • Google Merchant sync

05Key Features

Everything the platform does, in one place.

  • Pharmacy compliance gate82 configured questions, 1,368 customer responses and 125 orders held for verification to date — without slowing ordinary checkout.
  • Unified order lifecyclePending → Confirmed → Processing → Shipped/Collected → Delivered for both delivery and click & collect, with bulk status updates.
  • Subscribe & SaveRecurring orders with configurable frequency and discount, renewed automatically by a background worker.
  • Loyalty pointsPoints earned per order, redeemable at checkout, with automatic expiry.
  • Review automation, two waysTrustpilot's own service plus self-hosted post-delivery emails, so requests keep flowing past the free-tier quota.
  • WooCommerce-compatible APILive orders in exactly the shape a WooCommerce REST API returns, for tools built against that contract.

06Engineering challenges & how I solved them

Real problems found against live production data — with the actual debugging path, not just the fix.

  1. Next Day Delivery was silently reverting to Standard+

    Symptom: Every processing order's shipping line read Standard Delivery — including customers who had paid the Next Day surcharge.

    Investigation: The checkout's shipping-quote effect refetched options on every postcode or quantity change and reset the selection to the first option each time.

    Fix: Applied the guard a later effect already used: keep the customer's choice unless it is no longer valid.

  2. Trustpilot invites hit their free-tier limit+

    Symptom: The review integration stopped producing new reviews once the monthly invite quota ran out.

    Investigation: Invites went out at order confirmation — before shipping — and depended entirely on a quota outside the platform's control.

    Fix: Added a second, self-hosted review request on the Delivered and Collected emails, correctly timed and gated behind config, with mobile-friendly buttons.

  3. Click & collect looked identical to missing shipping data+

    Investigation: With an empty shipping-lines section, external systems could not tell a £0 collection order from missing data.

    Fix: The order feed always emits an explicit local-pickup shipping line for click & collect, even at zero cost.

  4. Refund windows needed a delivery date that did not always exist+

    Investigation: Refund eligibility runs from delivery, but only shipment tracking records it — and collection, manual and imported orders have none.

    Fix: Resolved the date from the latest tracked delivery, falling back to the order's last update, identically everywhere the window is enforced.

Case study

Next Day Delivery was silently reverting to Standard

Problem

Every processing order's shipping line read Standard Delivery — including customers who had paid the Next Day surcharge.

Investigation

The checkout's shipping-quote effect refetched options on every postcode or quantity change and reset the selection to the first option each time.

Solution

Applied the guard a later effect already used: keep the customer's choice unless it is no longer valid.

07Impact

What changed once the platform was in place.

Orders fulfilled
23,000+
Customer accounts
17,000+
Shipments dispatched
11,500+
Products
3,300+
  • Enforced a legally required pharmacy step without slowing checkout for the majority of orders.
  • Found and fixed a live bug downgrading paid Next Day orders to Standard — from the order feed, not a complaint.
  • Kept review requests flowing past the free-tier limit and re-timed them to after delivery.
  • 23,000+ orders and 11,500+ shipments processed with live Stripe payments.

ASP.NET CoreEF CoreSQL ServerNext.js / ReactClean ArchitectureMediatR / CQRSStripe & PayPalWooCommerce API compatibilityCompliance workflowsRBACEmail deliverability

Second storefront · live since Apr 2026

The sister storefront

A second brand's store, stood up on the same proven foundation instead of a fork

A second, independently run health and wellness storefront built on the same Clean Architecture foundation — its own database, domain, catalogue and payment credentials, standing on proven backend and admin code rather than a from-scratch build or a fork that drifts from day one.

Orders processed
1,200+
Customer accounts
500+
Products
3,100+
Shipments
900+
  • Full storefront parityCatalogue, cart, checkout, Subscribe & Save, loyalty, click & collect, discounts, blog and banners.
  • Granular RBACPer-page, per-action permissions for staff and roles, more strictly typed than the original.
  • Email Logs monitoringSent, pending, failed and permanently failed emails, with retry, filtering and search.
  • Google Merchant syncScheduled product feed and a key-secured review feed with its own credentials.
  1. A new admin page broke the production build+

    Symptom: npm run build failed: Module not found '@tanstack/react-query'.

    Investigation: The package had never been installed, and this platform's admin shell had no QueryClientProvider — so it would have failed at runtime too.

    Fix: Added the dependency at the version proven on the sister platform and wired a query provider into the admin tree for every current and future page.

  2. A backend contract had drifted from its frontend type+

    Investigation: The permissions endpoint returns a dictionary keyed by page, but its frontend type claimed a string array — hidden until now by an `any` escape hatch.

    Fix: Corrected the return type against the controller's real response and removed the need for `any`.

  3. A product-type union was missing a value the code relied on+

    Investigation: The local Product type had been narrowed to "simple" | "grouped", silently dropping "variable" while pricing and stock logic still branched on it.

    Fix: Restored the missing member to match the sister platform and the data the API actually returns.

Have a similar project?

Let's build something great together.

From shipping platforms to custom business tools — I can help turn your idea into reality.

  • Free consultation
  • Clear roadmap
  • On-time delivery