Material Matters: ERP, store and AI assistant
As sole engineer, I built a lead-to-cash ERP for Material Matters, the India distributor of SAGA. It has 150+ API routes, and one 917-product catalogue feeds every quote, GST invoice, vendor PO and the website. I also re-platformed materialmatters.in as a headless Next.js store on the CRM API, and shipped a CRM assistant that answers staff questions with citations.


- 150+ERP API routes
- 917products in one catalogue
- 31CRM API routes behind the store
- 1.65 GBmigrated off Sanity, zero failures
01 · The brief
One catalogue, every document, one engineer
Material Matters is the India distributor of SAGA. It sells furniture and workplace products from its own range and from partner houses such as Kokuyo, Minister and Boss Design, then delivers and installs them across India. Every part of that business needs the same product data. A quote needs it, a GST invoice needs it, a purchase order to a vendor needs it, and so does the website.
I was the sole engineer, from architecture to production. The goal was a lead-to-cash ERP where all of these read from one catalogue, so a product is defined once and every document and the website agree. The design had to respect a few hard rules:
- GST invoice numbers can't have gaps, even when two people raise invoices at the same moment.
- Several staff edit the same records, so one person's save must never silently overwrite another's.
- A payment must be applied exactly once, however many times the gateway retries.
- Each role sees only its own data, in every page and on every API call.
- One engineer builds and runs it all, so every part has to be simple enough to own.
- Role
- Sole engineer, architecture to production
- Client
- India distributor of SAGA
- Company
- The Sixty One (61 FZCO)
- Timeline
- 2025 — Present
- Scope
- ERP · CRM API · storefront · AI assistant · payments




The store reads the same catalogue
materialmatters.in is the public face of the catalogue. I re-platformed it as a headless Next.js store that gets everything from the CRM API, so nothing is typed in twice.
The filters, category counts and prices come from that API. So does each product's choice between Buy now and Price on request. Product images are served straight from the CRM's storage. When staff change a product in the ERP, the website shows the change.


Product page: price, GST, variants and lead time all come from one catalogue
materialmatters.in/products/robust-102 · Re-platform
Cached pages that refresh when the catalogue changes, and a migration with zero failures
A cached page is fast, but it can show an old price. A live page is always current, but it's slow. The store uses tag-based cache revalidation to get close to both. Pages stay cached until a staff edit invalidates the matching tag, and then only those pages are rebuilt with the new data. Open tabs also check a small content-version endpoint and refresh when the catalogue changes.
The old site ran on Sanity. I moved its products and media into the new system and checked every file against its SHA-1 hash after the move. The site no longer depends on Sanity's CDN.




03 · Integrity and payments
Correctness built into the data layer
In an ERP, a bug can mean a wrong invoice, so I put the guards in the data layer instead of relying on everyone being careful. Optimistic locking and compare-and-swap gapless invoice numbering protect concurrent writes, per-page RBAC is enforced at the edge and on every API call, and Razorpay runs on the raw REST API, where every webhook has to pass three checks.




04 · CRM assistant
An assistant that shows its sources
Staff ask the CRM questions in plain language, and the assistant answers with citations. Answers cite the CRM records they came from, so anyone can check them.
There is no vector database. Retrieval is BM25 keyword ranking across 10 record types, filtered by the asker's role. Answers are generated through a gateway over Gemini, GPT and DeepSeek, with fallbacks between providers.



