CASE 03 · STEMWISE

Building and running a production SaaS, end to end.

It started as my own spreadsheets for wholesale orders and inventory, and they were too slow. What replaced them now runs purchasing and sales for 20+ businesses, $200K+ through it.

(TL;DR)

SITUATION
I ran my own wholesale orders and inventory in spreadsheets, re-typing every order by hand, with the same plant named a dozen different ways.
WHAT I DID
I designed and built the whole product: the dashboards, the ordering flow, the layer that matches a plant’s many spellings to one name, and the pricing engine inside the database itself.
RESULT
20+ businesses run purchasing and sales through it, $200K+ combined, on 51 tables verified against the live database, 2026-08-31.

(WHERE IT STARTED)

It started as my own spreadsheets, and they were too slow.

Before there was a product, there were two spreadsheets, and I was the one keeping them up to date.

I ran my own wholesale orders in one workbook and my inventory and sales in another. Every order was arriving from a different platform and got copied in by hand, every plant name was typed a different way each time, and the totals only told me the truth after I had already redone the math. I wanted it to be faster, and I wanted to teach myself more coding, so I built the thing that replaced both.

REDRAWN FROM MY ORIGINAL SHEET · PLANT VENTURE, 2025
REDRAWN FROM MY ORIGINAL SHEET · PLANT VENTURE, 2025 · CUSTOMER NAMES REMOVED

(THE PRODUCT)

The dashboards customers run, and the site that sells them.

Stemwise is one place for a plant business to keep its stock, its orders, and its money, instead of a folder of spreadsheets.

The public site and the dashboards Stemwise customers work in today, owned end to end from the first sketch to production.

The main Stemwise dashboard
THE MAIN DASHBOARD · LIVE PRODUCT
The Stemwise plants dashboard
THE PLANTS DASHBOARD · VARIETY, STAGE, LINEAGE
SCROLL-THROUGH OF THE LIVE SITE · CAPTURED 2026-08-30

(THE DATABASE)

The part nobody screenshots.

Every plant I buy arrives in a batch, and batches bought a few months apart can cost wildly different amounts. The database works out what each sold plant actually cost, which is the number the books call cost of goods sold, or COGS.

The rule is called FIFO lot costing: each batch keeps its own cost, so a sale is priced against the batch it actually came from. It runs inside the database rather than in the app code on top of it. There is one version of the money math, and no screen can drift from it.

Plant prices fall fast: about 90% in two months is normal. Monstera Bulbasaur tissue cultures, which are plants grown from cells in a lab and sold small, went from $300+ retail to $27 in two months. Sell today’s stock at today’s average cost and the profit is a guess, because the cheap plants that landed last week are quietly subsidising the expensive ones that landed in spring. Charging each sale against the batch it came from is what makes the profit on it a real number.

REDRAWN FROM MY ORIGINAL SHEET · MOCHI’S JUNGLE WHOLESALE, 2026 · MONSTERA BULBASAUR, ROW 61, AT $20
The Stemwise database redrawn as a flow: FIFO lot consumption and the COGS engine

SCROLL THE DIAGRAM SIDEWAYS TO READ IT →

51 TABLES · 92 FUNCTIONS · 85 RLS POLICIES · VERIFIED AGAINST THE LIVE DATABASE, 2026-08-31

Row level security, or RLS, is a set of rules kept in the database itself deciding which rows each account is allowed to see. The tables are the lists the product keeps; the functions are work the database does on its own instead of waiting to be asked.

(THE ALIAS INTELLIGENCE)

Teaching the data to recognize a plant.

The same plant gets typed a dozen different ways. One record says Albo, another says Monstera Albo, another says PBV. A person knows those are one plant. A database does not, unless it is taught.

Each of those spellings is an alias, which is just another name for the same plant. Every alias points at one canonical name: the single official spelling everything gets counted under. When two records turn out to be the same plant after all, one merge folds them together and rewrites the history behind them so nothing is counted twice.

1,636 messy names → 491 plants

I kept this by hand first: a tab that mapped whatever a plant had been called this week onto the name I actually used. It worked until it did not, which is the point where a list kept by hand has to become something the database does on its own.

REDRAWN FROM MY ORIGINAL SHEET · PLANT VENTURE, 2025
The Stemwise alias resolution flow: aliases and canonical synonym pairs resolving to one variety

SCROLL THE DIAGRAM SIDEWAYS TO READ IT →

ALIAS MATCHING · SCOREBOARD

The product writes most of these extra names itself, from rules like dropping the genus off the front of a name. Before any generated name ships, one check asks whether that same word already points at a different plant. It catches two plants claiming one word. It does not judge whether a name points at the right plant; the audit that follows is where a wrong match would show up.

1,528 of 1,530 generated aliases shipped without a name collision, 99.9%

generated aliases shipped without a name collision

99.9%

two names for two plants collided; both were caught before shipping

VERIFIED AGAINST THE LIVE DATABASE, 2026-09-01

THE CAUGHT CASE

One rule drops the genus off the front of a name. Two different plants were left answering to the same single word, so the check refused to create either name rather than guess which plant a customer meant.

  • "Veitchii" · Platycerium Veitchii vs Anthurium Veitchii2026-05-07

491official plants in the library2 merged by hand

genus_prefix800variegation_suffix405typo195strip_variegated130
ALIASES GENERATED, BY RULE · 1,530 TOTAL · SCALE 0-800ONLY GENUS_PREFIX COLLIDED: 798 SAFE, 2 CONFLICT

These are the product’s own names for its rules. genus_prefix, the only one that ever collided, drops the genus off the front of a name, so a record reading Monstera Albo also answers to Albo.

THE TWO NEW PLANTS

  • Monstera Deliciosa Mint NOID (no entry in the library yet: not the same plant as Monstera Deliciosa Mint)2026-07-31
  • Alocasia Sedenii Pink Variegated (no entry in the library yet: only Sedenii Aurea exists)2026-07-31

THE AUDIT

Separately I checked every extra name sitting on a real customer record. Each one should be linked to an entry in the plant library, the master list of official names, so the product treats the two spellings as one plant. Seven were not.

  • 71names on customer plant records
  • 62linked automatically
  • 7sat unlinked
  • 2new plants, no library entry

THE FINDING

Nobody typed those seven. They were made by merges. When two records turn out to be the same plant, I merge them. The losing record’s names are copied onto the winner, and its own name is kept as one more alias. That copy saves the plant, the person and the text, and stops there. It never fills in the link to the plant library and never goes looking for one. So there are two ways a name gets added and only one of them links: typing a new name links it, merging links nothing. That is how “Alocasia Pink Sanderiana” can match a library name letter for letter and still sit unlinked.

WHAT CHANGED

  • The seven are now linked to the plants they belong to.BACKFILLED 2026-09-02 · 69 OF 71 LINKED
  • Merging now carries the library link across instead of dropping it, so a merge can no longer leave a name attached to nothing.FIX APPLIED 2026-09-02
  • Matching a name now tries the exact spelling first, then names shared across every account, then a tidied version of the spelling with the variegation wording, punctuation and capitals evened out. Whenever the library gains an entry, everything still unlinked is checked against it again in the background.APPLIED 2026-09-02
  • Unlinked names now surface in a candidates view with how many customers use them. Monstera Deliciosa Mint NOID and Alocasia Sedenii Pink Variegated are the two on it today.SURFACED 2026-09-02
  • Promoting one of them into the canonical library is still a hand step.STILL OPEN

THE SEVEN, AND WHERE EACH BELONGS

EACH NAME IS MATCHED TO THE PLANT ON THE CUSTOMER’S OWN RECORD, NOT GUESSED FROM THE SPELLING

  • Philodendron Jose Buono Variegated → Philodendron Jose Buono2026-06-04
  • Alocasia Polly Mint Variegated → Alocasia Polly Ghost Mint Variegated2026-06-04
  • Alocasia Scalprum Mint Variegated → Alocasia Scalprum Mint2026-06-04
  • Alocasia Pink Sanderiana → Alocasia Pseudo Sanderiana Pink Variegated2026-05-28
  • Philodendron Burle Marx Variegated → Philodendron Burle Marx2026-05-26
  • Monstera Deliciosa Ocean Lava → Monstera Ocean Lava2026-05-26
  • PBV → Alocasia Pink Black Velvet (abbreviation)2026-04-30

The headline is a collision-free rate: of the 1,530 names the generator produced, 1,528 shipped without a second plant already claiming the same word. It is not a measure of whether each name points at the right plant. The audit under it is counted rather than scored on purpose, because 71 names is too few for a percentage to mean anything. Both are a dated snapshot of two queries against the live database, not a live feed; refreshing them is a rerun of the recorded SQL, and the date above moves with it.

(ORDERS THAT RUN THEMSELVES)

One link replaces the back-and-forth.

Wholesale orders used to arrive as messages on four or five different apps and get copied into a spreadsheet by hand. Now the buyer fills in one form and the order is already in the system.

A customer opens the wholesale form, or a presale form where people order before the plants have arrived. They pick plants at live prices and can still edit their own order afterwards. Demand adds itself up as the orders come in, and every finished order is priced against the batch it came from, by the same rule as everything else.

SCROLL-THROUGH OF THE LIVE PRESALE FORM · CAPTURED 2026-08-31
The live Stemwise presale order form, empty
THE LIVE FORM, EMPTY AND READY TO FILL · NO CUSTOMER DATA · PRICES ARE THE PRODUCT’S OWN LIVE ESTIMATES

(SKETCH TO FEATURE)

A customer sketched what she needed on a sticky note. Three weeks later the feature was live.

One customer’s sticky note started the mother-plant feature: tracking the big plants that every cutting is taken from. Her sketch, the DMs it arrived in, and the shipped screen that shows which mother each plant came from are their own read.

3 WEEKS · REQUEST TO LIVE

READ THE FULL CHAIN →
A wholesale grower’s sticky-note inventory sketch

(HOW IT GOT BUILT)

Stemwise and Mochi’s Jungle run part-time: designed, built, and operated nights and weekends alongside full-time work.