Six templates. Then the reason they broke.
The engagement started the way retail engagements usually start: design the product detail page, the listing page, the homepage, and the supporting templates around them. Comps. Redlines. Ship.
The pages were not the hard part. The hard part arrived with the first question the comps could not answer — what does the add-to-bag button say when no size is selected? Four plausible answers, no rule, and the same question waiting behind every other component. A page answers it once. A system answers it every time.
So the scope moved. I kept delivering templates, and underneath them I defined the thing the templates were actually made of: a component library, a state taxonomy for each component, and a colour system where every value carried a job description instead of a mood.
The button that had to say four things.
This product page is long. Details, sizing, shipping, recommendations, ratings, a wall of customer photos, two more carousels. By the time a shopper has read enough to decide, the thing they decide with is a thousand pixels above them.
So the add-to-bag action detaches and follows — and once it follows, it has to carry the whole variant transaction with it, including the ways that transaction fails. The most common add-to-bag failure is not a server error. It is an unselected size. Which makes the error state the most important state on the most important control on the highest-value page on the site.
Sticky add-to-bag · state machine Recreation — interactive
Product name and prices are invented. The states, and the rule attached to each one, are the deliverable.
State 02 is the one worth arguing about. The obvious answer is a toast — leave the button saying Add to bag, throw an error when it fails. We put the instruction in the button, because a toast reports a failure and a label describes what the control will do next. Same information, no blame, nothing to dismiss, and nothing that can land under a thumb.
A disabled button is a designer refusing to say why.Djoaniel Hernandez · System note № 05
I designed the listing page with every filter on.
Filter chips are the easiest component in retail to design and one of the easiest to ship broken, because the comp always shows two or three of them. Nobody selects three filters. People select a colour family, then a couple of sizes, then a sleeve length, then change their mind and leave the old ones on.
So the specimen I designed against was the maximum: every colour, every size, every sleeve length, all applied at once. Run the slider up and watch the second row go under — the number that matters is not the chip count, it is the height of the row, because that height is subtracted from the products. The fold is drawn in and everything past it is dimmed rather than deleted, because the products do not vanish; they stop being looked at. The first row never crosses the line. The second one pays for every chip you add.
Listing page · filter row at load Recreation — interactive
Drag, step or arrow-key from an empty row to every filter in the facet set. Everything below the slider is measured from the live DOM, not asserted.
0 · clean7 · a plausible session31 · max load
Result count and product names are placeholder values, exactly as they were in the spec. Row height, wrap count and fold clearance are measured live from the DOM. The page inside the frame is laid out at a real 1440px and scaled to fit — so every number in the strip is a logical pixel on a reference page, not a band pixel dressed up as one. The fold is 900px unless your own window is shorter, in which case it is yours: the short window is the failure case, and the failure case is the one worth showing.
Three rules came out of that specimen. Chips wrap rather than scroll, because a horizontal rail hides the filters a shopper most wants to remove. Clear all is pinned first and never wraps away, so the escape hatch cannot leave the screen when the mess is at its worst. And the grid holds a fixed minimum above the fold — the filters are allowed to get ugly, the products are not allowed to disappear.
The version nobody frames is the real deliverable.
The homepage went out twice: once dressed in campaign imagery, and once as grey boxes. The second one is the one I actually designed.
Because the person who touches this page every week is not the shopper. It is a swapping a hero, three promo tiles, a five-product rail and a give-back banner through a CMS, on a campaign cadence, with no designer in the room. If the layout only holds when the photography is beautiful, it does not hold — it degrades a little every week until somebody calls it a redesign.
Homepage template Recreation — toggle the fill
Summer
and sweet
lifted
it all
accessories shop
The grey state is the deliverable, not the failure state. Toggle it off and you have what the merchandising team actually receives on a Friday — every slot still declaring a ratio, a safe area and a character budget. The page has to hold on a week when the assets are late, because most weeks they are.
Each slot is a contract, not a canvas. A hero, three promo tiles, a five-product rail, a give-back banner — the shapes are fixed before anyone chooses an image. A merchandiser cannot break this page by picking a weak photograph, only by leaving one out.
Nothing here is two designs. The fields re-dress in place rather than swapping pictures, and the readout changes with them — because the claim is that one layout survives both conditions, not that there is a pretty version and a plain one.
Campaign photography belongs to the client and is not reproduced. In the populated state the palette itself stands in for the imagery — which is, conveniently, the point being made.
A palette is not a mood board. It is an assignment sheet.
The colour documentation does not describe how the colours feel. Each value carries the job it is allowed to do, so that a developer, a merchandiser or the next designer can resolve a question without a taste debate. Two of the entries are arguments rather than choices.
Hex values on this page are shifted from the source palette. The assignments are the subject; the exact values are the client's.
The palette also shipped with PMS numbers, because this brand exists in stores. A colour that only resolves on a screen is half a colour system — the same peacock has to survive a printed tag, a window graphic and an OLED phone, and the one that governs all three is the one worth writing down.
And every field has seven.
The same discipline, one level down. A text input is not a rectangle; it is seven rectangles a developer has to be told about before they guess.
Buttons carried the same treatment — four hierarchies, desktop and mobile, redlined to a 47px target.
The edges of this one.
The reason this project sits in a portfolio next to a banking data standard and a chatbot architecture is that it is the same job. Find the moment the system is asked a question it has no answer for, and answer it once, in a place where the answer survives the next person. In banking that moment was a missing valuation. Here it was a shopper who had not picked a size.