LiveSince 2026
Web · Admin
Architecture, backend, storefront and admin
Solovit Store
A self-hosted, bilingual online store for an Egyptian supplements brand: cash on delivery, a customer wallet, loyalty points, and an admin the owner's staff run the business from.
Commits since July 2026
Test files: unit, API and end-to-end
Languages, Arabic first

01/Problem
The brand needed its own store, not a rented one: Arabic-first content, cash on delivery, shipping priced per governorate, and staff who also take orders on WhatsApp.
It also had to grow with the business: offers, a wallet, loyalty points and campaigns were added while the store was already taking orders, without breaking the money.
02/Constraints
- 01Arabic and English for the interface and the product content, entered once in the admin.
- 02Money must stay exact: wallet, points and discounts can never drift from what the customer saw.
- 03Real ad attribution, with tracking only after the visitor consents.
- 04Self-hosted on one server with nightly backups.
03/Architecture
Customers
- Storefront · Next.js 15
- next-intl ar/en
- Meta Pixel + CAPI
Staff
- Admin · Medusa v2
- orders & analysis
- wallet · loyalty · lucky game
Commerce core
- Medusa modules
- custom ledgers
- scheduled jobs
Data
- PostgreSQL 16
- Redis 7
- Cloudflare R2 + CDN
04/Decisions
Never take an order at a total the customer didn't see
Placing the order re-prices shipping and re-applies promotions. If the total moves at that moment, the order stops, the page refreshes and asks the customer to review the new total, instead of silently charging a different amount.
Wallet and points as ledgers, not balances
Every credit and spend is a ledger row. Points are earned only when an order is delivered and paid, and reversed on refusal or cancellation. Writes are idempotent and serialized per order, so a double click never credits twice.
Trade-off: More code than a single balance column, and every new feature has to say how it reverses.
Attribution from the server, after consent
Browsers block pixels. Purchases are also sent server-side through Meta's Conversions API with the click identifiers, so the owner sees which campaign sold, and an admin page shows whether tracking is actually working.
AI fills the product page, a person checks it
The new-product editor gives staff a ready Arabic prompt for any chat model. They paste the JSON back and every text field fills in both languages. Prices, sizes and images stay manual; the parser tolerates wrapped JSON and fills only the keys present (11 tests).
05/Screens


06/Stack
Medusa v2Next.js 15React 19TypeScriptPostgreSQL 16Redis 7next-intlCloudflare R2Meta CAPIVitestPlaywrightDockerCaddy