A few months ago, I set out to build a complete, production-ready e-commerce
platform for a luxury perfume boutique in Algeria. Not a tutorial clone — a
real, deployed, fully functional storefront with a custom admin dashboard,
live shipping integrations, and a premium UI.
Here's what I built and what I learned.
🔗 Live Demo
📦 Source Code
👉 https://github.com/abdouh071/perfume-ecommerce-store-dashboard





🧱 The Tech Stack
- React.js + Vite — Fast, modern frontend
- TailwindCSS — Utility-first styling
- Firebase — Firestore (database), Auth, Cloud Functions, Hosting
- Framer Motion — Smooth animations
- ImgBB API — Dynamic image hosting
✨ The Design: Liquid Glass UI
The biggest design challenge was making something that feels genuinely
premium — not just another e-commerce template. I went with a "Liquid Glass"
aesthetic: glassmorphism panels, smooth Ken Burns hero carousel, and subtle
micro-animations on every interactive element.
🚚 The Hard Part: Algerian Courier Integrations
This is where things got interesting. Algeria has its own local delivery
ecosystem: Yalidine, Maystro, Ecotrack, ZR Express, and about 15 others.
None of them have great documentation.
I built a unified shipping layer that:
- Fetches live shipping rates per wilaya (province)
- Loads available StopDesk pickup points at checkout
- Dispatches orders to the courier with one click
- Downloads official shipping labels as PDF
- Auto-updates order status via webhooks
The CORS Problem (and how I solved it)
Calling courier APIs directly from the browser causes CORS errors and exposes
your API keys publicly. My solution: Firebase Cloud Functions as a proxy.
Every shipping API call goes through a Cloud Function. The frontend never
touches the API keys — they live securely on the server and are fetched
directly from Firestore when needed.
javascript
// Frontend — no credentials needed!
const rates = await fetchRates(null, null, '16');
// Cloud Function — reads keys from DB securely
const snap = await admin.firestore()
.collection('settings').doc('shipping').get();
const credentials = { token: snap.data().apiToken, ... };
Top comments (0)