
Three markets, one platform
One marketplace running three separate markets: hiring freelancers, buying courses, and finding software.
An online marketplace for cakes, sweets and gifts, where sellers take orders for delivery or pickup.

Chocowi is an online marketplace for cakes, sweets, chocolates, gift baskets, bouquets and party services. Buyers find sellers near them, order for delivery or collection, and pay by card. Sellers get their own storefront, take and manage orders, and withdraw their earnings. It is live at chocowi.com and was built for a client.
A buyer browses or searches by category, price, rating or location, and the homepage surfaces sellers close to them. On a listing they see the photo gallery, the ingredients and allergy information, and reviews from other buyers, then pick their options and add it to the cart, or message the seller to ask for something custom. At checkout they choose delivery or collection, set the date they need it for, and pay. After that they can follow the order status, track the shipment, message the seller, leave a review scored on six separate things, and open a dispute if something goes wrong. They can also save listings to a wishlist, keep a list of favourite sellers, and see prices in their own currency.
A seller signs up as an individual or as a company and gets a public storefront page. They list products or services, choose how each one is priced, block out dates they cannot take work, and move each order through its stages. Their earnings build up in a dashboard showing available balance, pending withdrawals and full history, and they withdraw to Stripe Connect, Wise or PayPal. Buyers can also post what they are looking for, and sellers send quotes back, which is one of the reasons to take the paid membership: it lowers commission, unlocks those buyer requests, and lifts a listing in search.
The most interesting engineering is in the pricing, because a cake is not one price. A listing can be sold as fixed packages, or with variable pricing where size, flavour and filling are separate option groups and every option carries its own price difference. Layered on top are quantity discounts, bulk price breaks, timed sale discounts, add on services charged per order or per unit, and shipping rules that change by region. The cart stores the exact combination the buyer picked, and the whole total is recalculated on the server at checkout, including platform fees and per state tax covering every US state and Canadian province, so a number edited in the browser cannot change what actually gets charged.
A lot of the business is negotiated in conversation, so the quote itself is a structured object inside the chat message, carrying price, delivery terms, add ons, deposit split and buyer questions. Accepting it drops the buyer into a checkout that is already priced. Bigger jobs can be split into a deposit now and the balance later, and the seller cannot mark the order delivered until that balance clears.
Orders follow a fixed sequence that differs for delivery and for collection, and a seller cannot move an order to out for delivery without entering the courier, tracking id and tracking link. The buyer confirms completion rather than the seller, and a scheduled job completes the order and pays the seller. Another job sweeps overdue orders every minute. Disputes can be settled directly between the two parties with refund proposals, or escalated to an admin who issues a binding split, and refunds come back as platform credit that can be spent on the next order.
Chocowi also runs a second wholesale marketplace on the same codebase, with minimum order quantities, tiered pricing, customisation offers with sample pricing, and company profiles carrying certifications and export markets. A single order document points at either a retail product or a wholesale listing through Mongoose refPath, so orders, chat, payments, disputes, reviews and the admin panel serve both markets instead of being built twice.
The admin side covers a five module analytics dashboard, an eight tab payout console, dispute arbitration, fee and membership settings, category and content management, and employee accounts with per page permissions.
A cake is not one price. Size, flavour, filling and add ons all change it, and the total has to match in the cart, at checkout and on the invoice.
Modelled pricing as named option groups where each option carries a price difference, snapshotted the exact chosen combination onto the cart item, then recomputed the whole total server side at checkout including fees and tax rather than trusting what the browser sent.
Most custom orders are agreed in conversation, so a quote had to become a real order without anyone retyping it.
Made the offer a structured object inside the chat message, carrying price, delivery terms, add ons, deposit split and buyer questions. Accepting it routes into a checkout that is already priced with fees and tax, and the offer status mirrors into both users' chat documents over Socket.IO.
Large custom orders needed a deposit, but a seller taking the deposit and never finishing is the obvious failure.
Added a deposit order type that can only be created from a chat offer, where the buyer pays part up front and the seller cannot mark the order delivered until the remaining payment has gone through.
Buyers forget to confirm delivery, which would leave sellers unpaid indefinitely.
Set a confirmation deadline three days after the seller marks an order delivered or picked up, then ran a cron that completes those orders, pays the seller, and labels the payment clearly as auto completed with no buyer response.
Running a retail marketplace and a wholesale marketplace usually means building everything twice.
Used Mongoose refPath so one order can point at either a retail product or a B2B listing, and at either a normal seller or a B2B company profile. Orders, chat, payments, disputes, reviews and the admin panel are written once and serve both markets.
Refunds from disputes and cancellations needed to move money back without a card refund every time.
Credited refunds to a platform credit balance on the user, spendable at checkout or on a membership and cashable out through the admin refund queue, which keeps the money on the platform instead of running repeated gateway refunds.