COD e-commerce platform for Algerian clothing shops — storefront + admin order dashboard. React, TypeScript, Express, Prisma, Supabase,PostgreSQL.
# Casbah
A cash-on-delivery storefront and admin dashboard for small clothing shops in Algeria, built around how these shops actually sell: no online payment, orders confirmed by phone, and a high return rate that the software has to treat as normal rather than exceptional.
The dashboard is the real product — it replaces the shop owner's WhatsApp thread and paper notebook.
---
## Live
| | |
|---|---|
| **Storefront** | *(add your Vercel URL)* |
| **Dashboard** | *(add your Vercel URL)*`/admin/login` |
| **Demo login** | `demo@casbah.dz` / `demo1234` |
The demo account is **read-only**: it can browse orders, products and stock, but every write is refused by the server. Enforcement lives in `server/src/middleware/reject-read-only.ts`, not in the UI, so hiding a button is not what protects the data.
---
## Screenshots
| Storefront | Product page |
|---|---|
| | |
| Orders | Order detail |
|---|---|
| | |
| Stock | Arabic (RTL) |
|---|---|
| | |
---
## Stack
**Client** — React · Vite · TypeScript · Tailwind v4 (CSS-first `@theme`, no config file) · React Router
**Server** — Node · Express 5 · TypeScript · Zod · JWT · bcrypt
**Data** — PostgreSQL (Neon) · Prisma 7 with the `prisma-client` generator and the `@prisma/adapter-pg` driver adapter
**Storage** — Supabase Storage, uploaded to directly from the browser via signed URLs so the service-role key never leaves the server
**Deploy** — Vercel (client) · Railway (API)
French and Arabic throughout, with full RTL. Mobile-first: most traffic here is phones.
---
## Three decisions worth reading about
### 1. Prices are never taken from the client
The order payload carries no prices at all — no `unitPrice`, no `subtotal`, no `shipping`, no `total`. Zod strips unknown keys by default, so a request that helpfully includes `"total": 1` has it discarded before any code could read it, and the order service never touches `req.body` for money.
Every figure is looked up server-side: the unit price from …