WorkCollab?ContactSign In
← WorkMulti-tenant SaaS

MANUFACTURING OPERATIONS UNDER THE STOREFRONT

Year

2024 → present

Role

Sole engineer

Status

Rebuild in progress

Stack

Next.js 16 · Supabase · Shopify

Manuva is manufacturing-operations software for Shopify-native product brands. Inventory, multi-level BOMs, production orders, purchasing, stocktake, reports, and capacity planning — connected, live, and tenant-scoped from the schema up.

v1 shipped as a fix for inventory drift in Shopify stores that assemble products from components. v2 — Manuva — is the broader rebuild. Shopify still owns the catalog and the demand signal. Everything else lives here: which components are on hand at which location, which are reserved, what came in from suppliers, what got counted on the floor, what a job should cost, how loaded each department is on a given day.

The problem

A manufacturer selling through Shopify usually runs two systems pretending to be enough. Shopify knows orders. The floor knows components, receipts, cycle counts, and labour. The moment products share sub-components, buy-to-build timing matters, or margin depends on who did the work, that split gets expensive — and the standard fix is either a stack of spreadsheets or an MRP whose per-seat bill grows faster than the team.

Manuva sits between them. Variants tie to versioned BOMs, orders to component reservations, purchase orders to goods inwards. Stocktakes apply variance back into the same ledger. Planned work rolls up into costing and capacity. One system covers the whole shop floor — from raw materials in to finished goods out.

The shape of the system

Shopify order
Active BOM
Reservation
Movement + Balance
Availability

Shopify order → Active BOM — webhook resolves the variant

Active BOM → Reservation — recursive explode down to components, with yield %

Reservation → Movement + Balance — append-only, transactional, per location

Movement + Balance → Availability — derived, refreshed on a short tick

Manuva is the operational layer under the storefront, tenant-scoped from the schema up. A Shopify order lands via webhook, resolves its active BOM, and reserves components before Shopify's own counters have been touched. The reservation writes into an append-only movement ledger, and the derived availability view is what the rest of the app reads.

Goods inwards, stocktake variances, and manual adjustments all enter the same ledger through the same invariant. Every balance has a movement behind it.

Shopify inventory is reference only. Manuva doesn't write stock levels back. It keeps its own movement ledger and balance tables per location, so availability, reservations, receiving, and reconciliation all live in one place.

The hard bits

One ledger for every inventory mutation

Supabase is the inventory source of truth. Shopify stays the sales channel, but operational availability lives in Manuva. Every receipt, stocktake variance, manual adjustment, and reservation writes an append-only movement record and updates the derived balance for that component and location.

That invariant matters because the app has to hold up under audit, reconciliation, and recovery. If a balance ever changes without a movement behind it, the system is lying. There is one code path for inventory math. No side doors, no hidden writes, no Shopify-only updates leaking through.

BOM versioning with yield % per line

Bills of material are multi-level and versioned. Each variant has one active BOM at a time, with a full history behind it. Lines carry yield %, so the explosion that drives reservations and costing reflects what actually comes off the line, not the idealised recipe.

Templates speed up the common case — a candle line that shares a wax base across thirty fragrances reuses one sub-assembly. Activating a new version doesn't break the past: old orders keep pointing at the BOM that priced and reserved them.

Allocating components from live Shopify demand

Orders sync in from Shopify and land as local orders and order lines. Each line immediately drives component reservations through the active BOM for the ordered variant. Availability stops being "how many finished goods are left" and becomes "are the required components on hand once already-reserved stock is taken out."

Cancellations release reservations. Fulfillments consume them. Missing BOMs, weak component coverage, and over-reservation all surface before the floor feels them.

Stocktake, purchasing, and goods inwards on the same ledger

Stocktake sessions run by location. They capture expected vs counted quantities, move through approval states, and apply the variance back into the ledger atomically. Purchase orders and goods inwards receiving use the same model — partial receipts line by line, bulk receipts when the dock fills up, supplier lead times tracked against reality.

There's no side channel for warehouse ops. Receiving, counting, and manual corrections all land on the same balances and movement history. Reports and audits read from one source.

Tenant isolation from the schema up

Manuva is multi-tenant from the database outward. Every operational table carries a tenant key, every RLS policy enforces it, every RPC is written so an unauthenticated path can't bypass it. The Shopify webhook handler is idempotent and tenant-scoped: a replayed delivery for one shop can't touch another's inventory.

An integrity audit runs continuously over the live data — reconciliation drift, over-reservation, over-receipt, duplicate movements. Anything that violates the invariant lights up before a customer or auditor finds it.

Capacity, costing, and the shop floor

Inventory isn't the end of the model. Open order lines can generate frozen cost snapshots pulled from the active BOM, labour routing, rate schedules, admin load, utilities, and overhead. The snapshot is the estimate the job was quoted against.

Actual time entries roll back into actual labour cost, margin, and department utilisation. That ties customer demand, material consumption, and shop-floor capacity into one model, where before they lived in three disconnected spreadsheets.

The result

The rebuild has working surfaces for components, products and variants, BOM management, orders, inventory, suppliers, purchasing, goods inwards, stocktake, costing, staffing, actual time, capacity, reports, and activity logging. Wider than an inventory-drift fix.

v1 proved the demand for component-aware inventory. Manuva is the operating system built around it — one place for materials, inbound supply, counted stock, planned margin, actual labour, and department load.

Tenant isolation runs in Postgres with RLS. Shopify ingest is idempotent. Every inventory mutation rides the movement-plus-balance invariant, and a continuous integrity audit watches it for drift.