The challenge
A store has to stay correct when real people use it. Stock can't oversell, prices can't be tampered with from the browser, coupons can't be abused, and the catalog has to be discoverable by search engines or nobody finds it.
Those are different problems that all meet in the checkout. The goal was a codebase where each guarantee has an owner and a test.
How I approached it
- 01
Server-validated cart and one-transaction checkout
Cart and checkout re-validate live price and stock on every mutation. Placing an order (stock decrement, payment record, address snapshot, cart clearing) happens in a single database transaction, so a failure leaves nothing half-done.
- 02
Inventory as an append-only movement ledger
Stock isn't a number that gets overwritten. Every change is a movement row, so admins can see why a quantity changed, and cancelled or returned orders restock automatically.
- 03
Coupons validated twice
Coupon rules (percentage or fixed, minimum order, discount cap, usage limits, per-customer limits, product or category restriction, active window) are re-validated server-side when the cart is viewed and again inside the checkout transaction.
- 04
A full order lifecycle
Orders move through pending, confirmed, processing, packed, shipped, out for delivery and delivered, plus cancel, return and refund. Inventory restock and Cash-on-Delivery settlement happen on each transition.
- 05
SEO built into the catalog
Product and category pages carry canonical URLs, OpenGraph and Twitter metadata and JSON-LD (Product, AggregateRating, BreadcrumbList). The sitemap and robots rules are generated from the live catalog, and private routes are excluded.
- 06
Production hardening
Foreign-key columns that are queried have explicit indexes, coupon, order and review actions are rate limited in the database, security headers are set, and the app has real error boundaries instead of framework defaults.
Deliberate trade-offs
- Search is a simple ILIKE match, which is fine at this catalog size. The README notes the upgrade path (Postgres full-text search with a GIN index) instead of optimizing early.
- There is no online payment gateway yet; checkout is Cash on Delivery, which matches the target market. A Content-Security-Policy is also deliberately deferred and documented.
What I built
- Modelled catalog, variants, inventory ledger, orders, coupons, reviews and wishlists with indexed foreign keys and migrations.
- Built the admin dashboard: revenue, orders, customers, low-stock alerts, coupons, review moderation and analytics.
- Extracted business logic (order totals, tax selection, coupon math, inventory math) into pure, unit-tested functions.
- Wrote 36 unit tests, 18 integration tests that always roll back, and a Playwright test of the full purchase flow.
- Documented architecture, database, environment and deployment in the repository.
What this project demonstrates
- Transactional checkout and inventory that can't oversell
- SEO-aware catalog pages with structured data
- A test pyramid: unit, rollback-safe integration and browser end-to-end