Skip to content
Abdu.
Live in productionCase study

Ethio Coffee Store

A live Saudi e-commerce platform that takes Mada and Apple Pay, ships through Torod in one click, and updates order status from payment and delivery webhooks.

Context

A registered commercial center in Jeddah sells Ethiopian coffee, spices and leather goods, plus products from Turkey and other countries, to customers across Saudi Arabia. It needed a store that takes the payment methods Saudi customers actually use, books shipments with local couriers and keeps customers informed, without staff copying order numbers between dashboards.

What I built

  • An Arabic-first storefront with an English toggle in Next.js, with RTL-correct product, cart and checkout flows.
  • A NestJS API that owns the order lifecycle through an explicit state machine (pending → paid → processing → shipped → delivered), on PostgreSQL (Neon) with Drizzle ORM.
  • Moyasar payments with Mada, Visa/Mastercard and Apple Pay. Every payment webhook is signature-checked, de-duplicated and confirmed by re-fetching the payment from Moyasar before the order changes.
  • A Next.js admin dashboard where staff ship an order through Torod: search the delivery city, compare courier rates and buy the label in one step.
  • Torod webhooks that mark orders delivered automatically, and customer emails (via Resend) when an order is paid and when it ships.
  • Production on Vercel (storefront and admin) and Render (API), deployed automatically on every push.

Architecture

CustomerWeb · MobileStorefrontNext.js · AR/ENAdminNext.js · staffOrder APINestJS · TSMoyasarMada · Apple PayTorodShipping APIPostgresNeon · DrizzleEmailResendCouriersSMSA and others
  • Users
  • My code
  • Services
  • Third-party APIs
  • Data

Hover or focus a component to see what it talks to.

Hard problems solved

  • Token lifecycle and retry

    Torod issues expiring bearer tokens. The client caches the token, refreshes it five minutes before expiry, shares one token request between concurrent calls, and re-authenticates once if Torod revokes a token early.

  • Webhook idempotency and the order state machine

    Payment webhooks are verified first, de-duplicated on the gateway's event ID, then confirmed against Moyasar. Torod updates re-fetch the shipment instead of trusting the webhook body, so duplicate or out-of-order events can't ship twice or move an order backwards.

  • Apple Pay domain verification

    Apple Pay on the web only appears on a verified merchant domain. The storefront serves Apple's domain-association file, so Safari and iPhone customers get the Apple Pay button at checkout.

  • Arabic RTL commerce UX

    Arabic is the default language. Prices, phone numbers, addresses and order IDs mix Arabic and Latin text, so the UI uses logical CSS throughout and keeps numbers and codes left-to-right inside right-to-left layouts.

Stack

  • Next.js
  • NestJS
  • TypeScript
  • PostgreSQL
  • Neon
  • Drizzle ORM
  • Moyasar
  • Apple Pay
  • Mada
  • Torod
  • Resend
  • Vercel
  • Render

Outcome

The store is live and taking real payments from customers in Saudi Arabia. Payments confirm themselves, shipping an order is one click in the admin dashboard, and delivery updates arrive on their own, so the team spends its time on customers instead of copying tracking numbers.

Need something like this?

Tell me about your business and the systems you already use. I'll tell you honestly what it takes.

Book a call
Next case studySOFA Digital Technologies