Fabric store: catalogue priced by the metre, bank-transfer payment with receipt review, reviews only from verified buyers.
A fabric shop in Samarkand: chiffon, awning fabric, lace and satin, brought in from Dubai, cut from one metre up and shipped across Uzbekistan.
The defining feature is that goods are sold by length, not by piece. Length is chosen on the product card, the price is per metre, and the cart stores centimetres. Mixing metres and centimetres inside money calculations is how rounding bugs are born, so the entire codebase keeps one unit — the centimetre — and converts to metres only when something is displayed.
The cart lives in the browser rather than the database: putting a cut of fabric aside should not require an account, and sign-in is needed only at checkout. But the prices in it are a display snapshot, never the source of truth. At checkout the server re-reads every item from the database and recalculates the total. Otherwise editing browser storage would be enough to buy silk for a hundred som.
Payment is a bank transfer with an uploaded receipt; the owner checks it and confirms. Only a customer whose order has been confirmed can leave a review, which is what keeps the reviews worth reading.
Built on the same foundation as the studio site — Next.js 15, Prisma, Auth.js — with its own design in warm gold.
A fragment of the project's real code — so you can see what's inside.
/** * Сколько сантиметров в метре. Вынесено в константу не ради * значения, а ради читаемости формул: total * CM_IN_METER * понятнее, чем * 100 посреди подсчёта денег, где сотни легко * спутать с копейками. */export const CM_IN_METER = 100;/** * ВАЖНО. Цены и названия в корзине — снимок для показа, не * источник истины. При оформлении сервер заново читает каждый * товар из базы и считает сумму по ней (см. createOrder). * Иначе достаточно было бы поправить localStorage, чтобы купить * шёлк за сто сумов. */const subtotal = lines.reduce( (sum, line) => sum + lineTotal(line.pricePerMeter, line.quantityCm), 0,);const totalMeters = lines.reduce((sum, line) => sum + line.quantityCm, 0) / CM_IN_METER;Project request
Fill in the form — we'll discuss scope and timing.
Integral — electronic gradebook
