TRAINYOURAGENT

Pink Salt Range: a wholesale salt business, back office and all, on one Worker

Most storefronts stop at the cart. This one carries the half of the business that comes after it: 32 tables covering suppliers, purchase orders, containers, lots, landed costs, shipments, invoices and quotes, served from 51 file-based routes on a single Cloudflare Worker with a D1 database. A buyer can pull the certificate of analysis for the exact lot their order shipped from.

The problem

A commodity wholesaler's website is the least interesting part of the business. The interesting part is that a container arrives, gets split into lots, each lot acquires a landed cost that is not the invoice price, and each lot has a lab certificate that a buyer in a regulated channel will eventually ask for by number. Most small distributors run that half on spreadsheets and the website half on a hosted store platform, and the two never meet. The consequence is routine and expensive: the price shown to a buyer is derived from a cost nobody has recomputed since the last freight change, and when a food-grade customer asks which lot their pallet came from, somebody opens a folder of PDFs. We built the storefront and the back office as one application so that neither question needs a human to answer it.

One Worker, one database, no separate backend

The whole application is server-rendered React on TanStack Start, compiled to a single Cloudflare Worker with the client assets bound alongside it and a D1 database bound as DB. There is no Node server, no separate API service and no second deployment target: one wrangler deploy ships the storefront, the back office and the schema migrations together. That shape is the reason the two halves can share a data model at all. A storefront on a hosted platform and a back office in a spreadsheet cannot share a definition of what a lot costs. Here the price a visitor sees and the landed cost an operator entered are two queries against the same tables.

One Worker, one database, no separate backend — specifics

The data model is the wholesale business, not the website

The 32 tables divide into roughly three groups, and only one of them is what a store template gives you. Commerce: items, stock, orders, payments, price_tiers, subscribers. Supply: suppliers, purchase_orders, po_lines, containers, lots, lot_shipments, landed_costs, sku_costs, shipments, shipment_lines. Trade: quotes, quote_requests, quote_lines, invoices, invoice_lines, deals, prospects, contacts, outreach_events, attribution. The supply group is what makes the pricing honest. A landed cost row exists per lot, so the cost of goods reflects the freight and duty actually paid on the container that lot came out of, not the supplier's invoice line. The trade group is what makes a wholesale enquiry a tracked object rather than an email.

The data model is the wholesale business, not the website — specifics

The custom domain is configured but not pointed

wrangler.jsonc declares pinksaltrange.com and www.pinksaltrange.com as custom domains on this Worker. The DNS for that domain does not resolve to Cloudflare today — the apex serves a 114-byte registrar parking page — so the application is reachable at its workers.dev address and nowhere else. This is stated rather than hidden because it is the difference between a thing that is built and a thing that is open for business, and the portfolio is not allowed to blur that. It is one DNS change, not a build task.

The numbers, and the command behind each one

Landed cost is the part that does not want to be a table

A landed cost is not a number that belongs to a product. It belongs to a lot, which belongs to a container, which arrived on a shipment that carried several lots and one freight invoice. Splitting that invoice across lots is an allocation choice, and whichever rule you pick, the result is that a SKU's cost of goods changes when a new container lands rather than when anyone edits a price. The modelling consequence is that sku_costs cannot be the source of truth; it has to be derived from landed_costs per lot and whatever stock remains from each. That is a straightforward query and a treacherous one, because a wrong answer looks exactly like a right answer until margin is reconciled at the end of a quarter.

Where it bites

What this entry does not claim

Stack and status

Built with TanStack Start, TanStack Router, React 19, TypeScript, Cloudflare Workers, Cloudflare D1, Tailwind CSS 4, Zod, GSAP and three / React Three Fiber. Relationship: Our own company. Stage: In production. Period: Jul–Sep 2026. Our role: Whole application — storefront, data model, back office, deployment Figures re-derived on 2026-11-13.