My Stack

My Stack

A routine builder on the Avnzor storefront — five time slots, automatic placement, and a classifier deciding what even counts as routine-able.

A routine builder on the Avnzor storefront — five time slots, automatic placement, and a classifier deciding what even counts as routine-able.

A routine builder on the Avnzor storefront — five time slots, automatic placement, and a classifier deciding what even counts as routine-able.

Bouguessa — Luxury Fashion on Shopify Plus

Hydrogen (React Router)
Shopify Customer Account API
Supabase
TypeScript
Claude Haiku (batch classification)

Where It Stands

Shipped and in use, but early: 35 stacks built, 62 items in them, and only 10 logged days. The gap between stacks created and days ticked off is the real finding — people will assemble a routine readily and forget to check it off, which is exactly the behaviour the replenishment features depend on. Runout prediction and streak nudges are built and have not yet had enough logging to fire.


There is also a live gap in the classifier. It was first run with narrower criteria, so a chunk of the skincare range still carries stale exclusion tags — and because tags win outright, those products cannot currently be added. Re-running the pass with the broadened definition is the next fix, and it ties directly into the wider catalogue taxonomy work.


If I were starting again I would make logging the first-class action rather than the second. The board is satisfying to build and easy to abandon; the daily tick is where retention actually lives, and it currently sits one screen away from where people land.

Role

Product designer & engineer

Year

2026

Industry

E-commerce · Customer retention

Stack

Hydrogen (React Router) · Shopify Customer Account API · Supabase · TypeScript · Claude Haiku

The Problem

A shopper buys a serum, a vitamin D and a cleanser in one order, then has to remember what to use when.


Avnzor sells supplements and skincare to customers who are, whether they use the word or not, building a routine. Nothing on the store acknowledged that. Products were sold as individual items, and the sequencing — morning or night, with food or before bed, together or apart — lived entirely in the customer's head.


My Stack turns that into a board of five time slots. An item can sit in more than one, because a cleanser genuinely is a morning and an evening step. Workout is deliberately time-agnostic and sorts last — it is bound to training, not to the clock.

Built into the Hydrogen storefront: an add-to-stack action on cards and product pages, a schedule board, daily check-off, and replenishment prompts in cart.

How I Framed It

The first real question was not how the board should look. It was which products are even allowed on it.


A serum belongs in a routine. A perfume does not. Neither does a lipstick, a hairbrush or a pack of cotton pads — they are bought from the same catalogue and look identical to a naive filter. Get this wrong in either direction and the feature reads as broken: too permissive and the board fills with things nobody schedules, too strict and half the skincare range cannot be added at all.


I resolved it as a cascade rather than a single rule. Explicit classification tags come first and win outright — set in batch by a Haiku pass over the catalogue, and editable by hand afterwards, so merchandisers get a free override without touching code. Below that sit a hard veto for the obvious non-routine categories, an ingestible signal backed by a supplement-vendor allowlist, and finally a topical routine-step signal.


The veto has a deliberate escape hatch. "Hair, Skin & Nails Gummies" reads cosmetic to any keyword rule, but it is a supplement — so an ingestible form overrides the veto. Most of the accuracy in this system comes from that one exception.

How I Framed It

The first real question was not how the board should look. It was which products are even allowed on it.


A serum belongs in a routine. A perfume does not. Neither does a lipstick, a hairbrush or a pack of cotton pads — they are bought from the same catalogue and look identical to a naive filter. Get this wrong in either direction and the feature reads as broken: too permissive and the board fills with things nobody schedules, too strict and half the skincare range cannot be added at all.


I resolved it as a cascade rather than a single rule. Explicit classification tags come first and win outright — set in batch by a Haiku pass over the catalogue, and editable by hand afterwards, so merchandisers get a free override without touching code. Below that sit a hard veto for the obvious non-routine categories, an ingestible signal backed by a supplement-vendor allowlist, and finally a topical routine-step signal.


The veto has a deliberate escape hatch. "Hair, Skin & Nails Gummies" reads cosmetic to any keyword rule, but it is a supplement — so an ingestible form overrides the veto. Most of the accuracy in this system comes from that one exception.

Key Decisions

Place the product for them, then let them move it. Dropping every addition into Morning would have made the board a to-do list the shopper has to sort. Instead placement is inferred, cheapest reliable signal first: the product's own usage directions are read before any keyword rule, because that is the label speaking rather than a guess — and it is parsed in both English and Arabic. Only if there are no directions do topical rules apply, then supplement keywords in a fixed priority order that resolves products matching two rules at once. A pre-workout is caffeinated and training-bound; workout wins.


Treat placement as convenience, not advice. Retinoids are placed at night because they photosensitise, and that is a real reason — but every suggestion stays editable. The system is scheduling a shelf, not dosing a patient, and the copy is careful about the difference.


Let people build a stack before they sign up. Asking for an account before a shopper has seen the value would have killed the feature. Guests build in session storage; on first login the whole thing is posted once as a merge and cleared. Nothing is lost at the account boundary.

The Constraint That Shaped the Architecture

Shopify OAuth and Supabase Auth are unrelated systems.


The storefront authenticates customers through Shopify. The stack lives in Supabase. There is no shared identity between them, which means the usual Supabase pattern — row-level security keyed to the signed-in user — simply does not work here. The database has no idea who the customer is.


So the tables carry row-level security with no policies at all, which locks out the public key completely, and every read and write goes through a server route holding the service-role key. Identity is the Shopify customer ID, resolved server-side only after the login check passes, and per-customer scoping lives in the queries rather than in the database's own rules. The browser has no path to Supabase whatsoever.


It is more code than the default pattern and it puts the burden on discipline in the query layer. Given two auth systems that will never know about each other, it was the honest option.

The Constraint That Shaped the Architecture

Shopify OAuth and Supabase Auth are unrelated systems.


The storefront authenticates customers through Shopify. The stack lives in Supabase. There is no shared identity between them, which means the usual Supabase pattern — row-level security keyed to the signed-in user — simply does not work here. The database has no idea who the customer is.


So the tables carry row-level security with no policies at all, which locks out the public key completely, and every read and write goes through a server route holding the service-role key. Identity is the Shopify customer ID, resolved server-side only after the login check passes, and per-customer scoping lives in the queries rather than in the database's own rules. The browser has no path to Supabase whatsoever.


It is more code than the default pattern and it puts the burden on discipline in the query layer. Given two auth systems that will never know about each other, it was the honest option.

More Projects

Creating Since 2010

I’m currently available for new work. Let me know if you need a digital designer. I’d love to talk about the next big thing!

© Molham.Works 2025