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

DashboardAll companies, today
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
Movements posted today, sample rows
TimeMovementPartQtyStatus
08:41ReceiveShaker base cabinet, 36 in24Posted
08:26Send to jobPorcelain tile, 12 by 24180Invoiced
07:44ReverseSlide-in range, 30 in1Reversed
07:15CountCabinet pull, matte black312Waiting
The dashboard, redrawn with sample values. Each tile drills to the rows behind it. The feed is the ledger itself: a count that found a variance waits for approval, and a correction posts as a reversal beside the original.

How the data moves

The sources

Purchase orders and deliveries scanned on a tablet, jobs imported from BuilderTrend, counts and adjustments

The ledger

Every movement posts once; corrections post a reversal; anything that moves stock is tested against a throwaway database first

The screens

Stock by company, jobs, purchasing and the dashboard, with a role deciding what each person sees

Kept honest

Each figure drills to its movements; over receipts, count variances and cross-company invoices wait for accounting

A delivery is scanned at the door, posts to the ledger, and shows up in the stock figure, the job it was bought for, and the invoice between the two companies.

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

Tell us the process no software handles.