NEWNow shipping: ACP · Google UCP · Retail MCP integrations
MnT Future
Client platform · India · Fashion D2C + in-store POSFashion D2C · Web store + POS + procurement

Lia Fashion

A fashion boutique selling online and over the counter, on one stock pool. Web store, admin, in-store POS and supplier purchasing in a single Laravel platform.

liafashion.in
Lia Fashion product
Role
Architecture + full-stack engineering
Platforms
Web storefront · Admin · In-store POS
Delivered
REST API · Admin back office · POS · Integrations
Status
Live and selling
Overview

Lia Fashion sells clothing on the web and from a physical counter. MnT Future built the platform behind both: a Laravel 12 REST API with a customer storefront, a full admin back office, an in-store POS, and supplier purchasing. The part that matters is that all of it reads and writes one inventory. A size sold at the till and a size sold online decrement the same row, under a lock, so the two channels cannot oversell each other. That is the same problem a US brand has the day it opens a retail door or a pop-up, and the same problem a marketplace has across fulfilment locations.

1 stock pool
Web store and in-store POS
154
API endpoints across 25 admin modules
Colour × size
Stock and price held per variant
Live
liafashion.in
The challenge

One garment, two tills

A boutique that sells in two places has one hard problem and a lot of easy ones. The hard one is that there is a single physical garment, in a single size, and two tills that can sell it. Run the shop floor on one system and the website on another and you oversell: the customer pays, and someone has to make an apology call. Everything else follows from that. Stock has to be tracked per colour and per size rather than per product, because a medium selling out is not the product selling out. Payments have to be reconciled rather than assumed, because a payment that succeeds at the gateway and fails to come back leaves an order in limbo. And the people running the shop needed the whole thing, including what they buy from suppliers, in one back office rather than three.

How we built it

A senior-led path from idea to live.

01

Model stock at the size, not the product

Every product carries its sizes as structured data with stock and price on each one, and colour variants carry their own imagery. Nothing in the system talks about a product being in stock, only a specific size of it.

02

Make the two channels share one write path

The POS does not get its own inventory logic. A counter sale and a web order call the same stock decrement, inside a database transaction that locks the product row until the sale commits, so two simultaneous sales of the last item cannot both succeed.

03

Treat payment as something to verify, not assume

Razorpay orders are created server-side, signatures verified, and webhooks handled. On top of that a scheduled command re-checks payments still sitting pending and reconciles them against the gateway, so a dropped callback becomes a resolved order instead of a support ticket.

04

Put the back office in one place

Orders, catalogue, coupons, banners, offers, shipping rules, reports, invoice settings, POS and supplier purchasing all live in the same admin, on the same auth, against the same data.

What we built

What we built

For shoppers

  • Catalogue with colour variants, each carrying its own gallery, and stock and price held per size
  • Registration by email OTP, or Google sign-in, with saved addresses and profile
  • Cart that applies bulk pricing on the total quantity of a line, not per add-to-cart, so splitting an order does not change the price
  • Coupon validation, tax and shipping rules applied at checkout
  • Razorpay checkout with server-side order creation and signature verification
  • Order tracking, with fulfilment raised automatically once payment clears

For the store team

  • In-store POS for counter sales, with its own invoice numbering and walk-in customer records
  • POS sales decrement the same size-level stock as the website, under a row lock, so the channels cannot oversell each other
  • Catalogue, category, coupon, banner and offer management with Cloudinary-hosted media
  • Order and transaction management, with pending payments reconcilable on demand
  • Supplier records and purchase entries, so incoming stock is captured where the outgoing stock lives
  • Reports exported as PDF or CSV, plus a dashboard over sales and orders
  • Company, invoice and payment-gateway settings editable without a deploy
Inside the product

What we shipped, on screen.

The storefront

The storefront

The catalogue customers browse. Colour variants carry their own imagery, and availability is resolved per size rather than per product.

Colour and size, priced separately

Colour and size, priced separately

Picking a colour swaps the gallery; picking a size resolves stock and price. The size is what the rest of the system tracks.

Engineering highlights

Where the hard problems were.

The decisions that keep a two-channel shop honest about what it actually has in stock.

One inventory, two channels

The website and the shop counter write to the same size-level stock. There is no nightly sync to go wrong, because there is nothing to sync.

The last item can only sell once

Stock decrements run inside a transaction that locks the product row, so two concurrent sales cannot both read the same stock and overwrite each other.

Payments get reconciled, not assumed

A command re-checks pending Razorpay payments against the gateway and resolves them, so a dropped webhook does not leave a paying customer without an order.

Buying and selling in one back office

Supplier records and purchase entries sit beside the catalogue and orders, so what comes in and what goes out are the same system.

Tech decisions

Engineering decisions

Every technology earned its place by solving a specific problem better than the alternatives.

Sizes as structured data on the product

Used for: Stock and price are held per size, and the API resolves availability at that level.

Advantage: A medium selling out does not hide the product. Apparel lives or dies on this, and bolting it on later means rewriting every stock path.

lockForUpdate inside the sale transaction

Used for: The product row is locked while stock is decremented, for POS and web alike.

Advantage: Two tills selling the last item at the same moment cannot both succeed. Without the lock both reads see the same stock and the second write silently restores it.

Scheduled payment reconciliation

Used for: An artisan command verifies pending payments against Razorpay, individually or in bulk.

Advantage: Gateway callbacks fail. This turns a class of silent revenue loss into a job that runs, which is unglamorous and worth more than most features.

Shiprocket raised on payment, not on order

Used for: Fulfilment is created once money has actually cleared.

Advantage: Nothing ships against an unpaid order, and the shop team never has to check twice before packing.

Laravel Sanctum with OTP and Google sign-in

Used for: Bearer tokens for the API, email-OTP registration, and Google OAuth alongside it.

Advantage: One token model covers storefront, admin and POS, so a permission is enforced in one place rather than three.

Tech stack

What it's built on.

Backend
  • Laravel 12
  • PHP 8.2
  • MySQL
  • Sanctum
Payments & fulfilment
  • Razorpay
  • Shiprocket
Media & documents
  • Cloudinary
  • DomPDF
Frontend & build
  • React
  • Vite
  • Tailwind CSS
FAQ

The questions buyers ask about this build.

No. It is a single-brand fashion business selling its own stock, online and over the counter. The vendor records in the platform are suppliers it buys stock from, not sellers on a marketplace. Our two-sided marketplace work is LOBBI, which is a separate story.

Because a garment in a given size exists once. If the website and the shop floor keep separate counts, the first busy Saturday produces an oversell, a refund and an apology. Sharing one write path removes the failure instead of monitoring for it.

The engineering transfers directly: variant-level inventory, one stock pool across channels, concurrency-safe stock writes, and payment reconciliation. The US-specific layer differs, so a US build swaps Razorpay for Stripe, Shiprocket for a US carrier integration, and adds the sales-tax engine and the ADA and PCI work we do as standard.

Yes. Architecture, the Laravel API, the admin back office, the POS, and the payment and fulfilment integrations. Published here with Lia Fashion's permission.

Selling in more than one place?

If your store and your retail, wholesale or pop-up channels keep separate stock, that is a rebuild worth scoping properly. Bring it to a free strategy session and we will map it.