Lumora
Lumora - an online store for a fictional lifestyle brand in Bangladesh, with server-side pricing, oversell protection, SSLCommerz and cash-on-delivery payments, digital downloads and a staff console. Built with Laravel 13 and React.
- Pet Project
- E-commerce
- Online Store
Lumora is a complete online store for a fictional lifestyle brand in Dhaka, Bangladesh. Customers browse homeware, kitchenware, leather goods, accessories, stationery and digital downloads, then pay online through SSLCommerz (cards, bKash, Nagad, Rocket) or with cash on delivery. Staff run orders, stock, the catalogue, coupons, reviews, customers and reports from a role-based console. The brand, its products, staff, customers and reviews are invented.
At a glance
- Role: Solo full-stack developer. I did the product design, backend, frontend, testing and deployment.
- Stack: Laravel 13, PHP 8.4, Inertia v3, React 19, TypeScript, Tailwind CSS v4, shadcn/ui, Motion, Recharts, Pest
- Quality: 264 automated tests, PHPStan level 7, Pint, linting and type checks
- Live demo: lumora.msar.dev
The problem
Small lifestyle brands in Bangladesh usually sell through Facebook pages or a generic store builder that doesn't fit how people here pay and get deliveries. The goal was a single store where:
- customers can pay with a card or mobile wallet, or with cash when the parcel arrives
- delivery is priced by district, across all 64 districts
- the last unit in stock is never sold twice, even when two customers check out at the same moment
- digital products (planners, prints, licence keys) are delivered automatically once payment is verified
- staff see every order, payment and stock movement from one console, and each person sees only what their role allows
Key features
Storefront: A home page, a shop with search, filters, sorting and infinite scroll, categories, curated collections, and product pages with variants (colour, size), a gallery, reviews, related products and a quick view. Customers can keep a wishlist, save addresses and track orders. Pages are server-rendered with JSON-LD (OnlineStore, Product, BreadcrumbList), a sitemap and robots rules.
Cart and checkout: The cart lives in the database and follows the customer when they sign in. Checkout supports coupon codes, guest checkout and delivery priced by district, with free delivery above a threshold. Cash on delivery has its own rules: no digital items, a zone that allows it and a maximum order total.
Order engine: Placing an order runs inside one database transaction. It locks the variants, re-checks stock, re-validates the coupon and re-prices the cart before taking stock. Every order keeps a snapshot of its prices, address and terms. Unpaid online orders hold their stock for 30 minutes, then a scheduled job releases it.
Payments: Payments go through a gateway interface with three drivers: SSLCommerz, cash, and a sandbox for demos. Every result is confirmed with the provider and checked for amount and currency. IPNs are signature-checked, and applying a result is idempotent. Each payment remembers its provider, so switching gateways never breaks refunds for older orders.
Digital products: Paid orders get download links with a download limit and an expiry date, served from a private disk. Licence keys are issued from an encrypted pool, and products that issue keys track stock equal to the keys left, so they can't be oversold.
Staff console: Includes a dashboard (revenue, orders to fulfil, low stock, top products) and reports with CSV export. It covers orders end to end: fulfilment, phone orders, cancellations, returns, partial refunds, notes and a timeline. It also manages customers, the payments ledger, products and variants, categories, collections, inventory with a stock ledger, coupons, review moderation, delivery zones, messages, staff, roles and settings.
Permissions: 16 abilities enforced through Gates, route middleware and Policies, with three default roles. The super-admin role is locked. Staff accounts support two-factor authentication and passkeys.
Technical challenges
Two customers, one last unit. Checking stock and then writing the order leaves a gap where two checkouts can both succeed. Checkout locks the variants with SELECT … FOR UPDATE, sorted by id so two checkouts can never deadlock, then re-checks stock and takes it inside the same transaction. The second customer sees "we don't have enough stock" and is never charged.
Prices in integer poisha. Every price is calculated on the server in integer poisha, in one place: subtotal, coupon discount spread across eligible lines (the last line absorbs rounding), delivery by zone, then VAT, included or added depending on the store setting. The browser never sends a price. If the total changed while the customer was on the checkout page, the order stops so they can review it.
Payments that arrive late or twice. A result can come from the customer's browser, the sandbox or SSLCommerz's IPN, and none of them is trusted on its own. Results are applied under a row lock, and a payment that is no longer pending is ignored. If a payment arrives after the hold expired, the stock is taken again if it is still there. If it isn't, the payment is refunded automatically and the customer is emailed.
Orders nobody can guess. An order page opens only for the owner, someone with the secret link from the order email, or the session that placed it or looked it up by reference and email. A reference on its own returns 404, so order numbers can't be enumerated.
Testing & quality
- 264 Pest tests covering pricing (VAT modes, coupons, delivery), checkout (stock, overselling, limits, cash-on-delivery rules, price changes), payments (idempotency, amount mismatch, late payments, digital delivery), cancellations and returns, SSLCommerz requests and IPN signatures, order access, storefront pages and SEO, and every admin area and its permissions
- PHPStan level 7 (Larastan) with 0 errors
- Laravel Pint for PHP style, plus linting, formatting and
tscfor the frontend
Architecture




Lumora is a fictional brand. Photography is from Unsplash.











