Inventory and purchasing system for a residential home builder group
Three related companies share one stock of building products. The system tracks every part by owner, receives deliveries by barcode, and raises the invoice each cross-company pull creates.
- Industry
- Residential construction, with a design showroom
- Go-live
- October 2026
- Who uses it
- Warehouse, purchasing, showroom sales, project managers, accounting
- Data
- Parts catalog, stock by company, purchase orders, jobs imported from BuilderTrend
- Stack
- Next.js, React, PostgreSQL on Supabase, Vercel
- Role
- Built by our founder, Hunter Warner
The problem
One company buys and holds the stock: cabinets, tile, fixtures, lighting, appliances, doors. Two sister companies pull from it for their jobs. Every pull is a sale between companies, so it needs a cost, a markup and an invoice, and accounting has to be able to prove each one.
A packaged inventory product tracks one company's stock. This needed three owners on the same shelves, allocations to jobs, and the invoice each cross-company pull raises, in one record.
What we built
A web app where every movement of stock posts once and stays. A correction posts a reversal beside the original, with a reason code, so the ledger never loses a figure. Any total on the stock screen drills to the movements that make it up.
Seven roles, from warehouse to accounting. New accounts start read-only and an admin grants the rest. Warehouse screens are built for a tablet, with large targets and barcode scanning.
Stock by company
Every part with six quantities: on order, on hand, allocated, on loan, available and consigned. Company tabs, filters, totals, and a detail panel with the part's movement history.
Receiving
Pick a purchase order, scan each line as it comes off the truck, and put it away. A line that arrives over the ordered quantity is held for approval before it posts.
Purchasing and vendors
Purchase orders per company with ordered against received, inbound totals and a late flag. Vendors with terms, contacts, and how many parts and open orders each one carries.
Jobs and invoicing
Jobs imported from BuilderTrend, each showing what is promised to it, what has been sent and at what cost, and the invoice every cross-company send raised at cost plus markup.
The parts catalog imports from a spreadsheet template with a per-row preview, and prints Code 128 label sheets. Settings hold the companies, locations with a bulk bin generator, categories with their markup, units, cost codes and operating thresholds.
What the dashboard shows
- Stock value on hand
- $1,964,000
- Available units
- 38,420
- Across 6 locations
- Allocated to jobs
- $590,000
- 30 percent of stock value
- Open purchase orders
- 31
- $486,000 committed
- Receipts waiting on approval
- 5
- 2 are over receipts
- Slow movers, over 90 days
- 132
- $74,000 held
| Time | Movement | Part | Qty | Status |
|---|---|---|---|---|
| 08:41 | Receive | Shaker base cabinet, 36 in | 24 | Posted |
| 08:26 | Send to job | Porcelain tile, 12 by 24 | 180 | Invoiced |
| 07:44 | Reverse | Slide-in range, 30 in | 1 | Reversed |
| 07:15 | Count | Cabinet pull, matte black | 312 | Waiting |
How the data moves
Purchase orders and deliveries scanned on a tablet, jobs imported from BuilderTrend, counts and adjustments
Every movement posts once; corrections post a reversal; anything that moves stock is tested against a throwaway database first
Stock by company, jobs, purchasing and the dashboard, with a role deciding what each person sees
Each figure drills to its movements; over receipts, count variances and cross-company invoices wait for accounting
The result
- One record of stock across three companies, with ownership on every row.
- Every cross-company pull raises its invoice at cost plus markup, and accounting sees it before it posts.
- A stock figure that proves itself: open any total and the movements behind it are there.
- Live since October 2026, with automated tests on every change before it reaches the live database.
Stack
Next.js and React with Tailwind. PostgreSQL on Supabase through Drizzle, with Supabase Auth for accounts. Hosted on Vercel, monitored with Sentry. Tests for permissions, the ledger, races and purchasing run on every push against a throwaway database, and migrations go to a test project before production.
Next project: Gable, a project management system for a residential home builder