Al-MadinaIttar
Four independently deployable projects sharing one backend: a customer storefront, a mobile app, an admin dashboard and a REST API that is the single source of truth.
The Challenge
One catalog, many surfaces
Web, mobile and admin all had to show the same products, orders and customers without drifting apart.
Discovery by scent
Shoppers browse perfume by fragrance family, not category, so the catalog needed scent-first navigation.
Friction at checkout
Customers needed to buy as a guest or with an account and still track their orders.
Running the business
The team needed to manage products, orders, customers and content from a single role-gated panel.
The Solution
MON TITRE
Full-stack developer
CLIENT
Al Madina Ittar
Web storefront
- Home, shop, product detail and collections
- Scent-family browsing and search
- Cart, wishlist and checkout with order confirmation
- Sitemap and robots for SEO
Mobile app
- iOS and Android from one Expo codebase
- Tokens kept in secure storage
- Mock-or-remote data seam: build the UI without a backend by flipping one env flag
Le produit en détail
Ce qui le rend différent
Accounts and orders
Dashboard, profile, saved addresses, order history and notifications, with guest checkout as an alternative.
Secure auth
JWT access and refresh tokens with single-flight refresh, plus role-based access.
Commerce rules
AED integer pricing, free shipping over 250 AED, standard or express delivery, readable order references (AM-#####) and loyalty tiers: Member, Connoisseur and Maison Elite.
Admin dashboard
Manage the catalog, orders, customers and content behind role-gated endpoints.
Les chiffres après six mois en production
Apps connected
Web, mobile, admin, API
Flow covered
Browse, checkout, fulfilment
Avec quoi il a été construit
Web
State
Forms
Mobile
Admin
Backend
Services
Défis et enseignements
Défis
Keeping four apps consistent
A single API contract ({ data, message } for success, { status, message, code, details } for errors, standard pagination) with Zod validation returning 422 kept every client predictable.
Slow work on the request path
Emails and notifications go through Redis and BullMQ queues so responses stay fast.
Server and client state
Server state lives in TanStack Query; cart, session and wishlist live in Zustand.
Enseignements
Layer + feature architecture pays off
Splitting by feature first, then by layer (routes, controller, service, repository, schema on the API; api, hooks, components, schema, types on the front ends) made all four repos easy to navigate.
Share schemas end to end
Typed TypeScript and shared Zod schemas for forms and API validation caught contract drift early.