MR-066Catalog product · the setup drawerStatesProductSource formulaStates
goes to another screengoes to another state of this screenfaded = not mocked yetEverything else — filters, sorts, tabs, modals — works, it just stays on this screen. The URL always names the state you are on, so any view can be copied and shared.
Catalog/Catalog Products/CP-0102Memopryl Brain SupportUpdated 2026-08-27, created 2026-06-30 by DJ
Setting up stoppedQuickBooks · 3 possible matchesneeds youNothing written · no item, no linkwaiting on youIt will not resume on its own.
Setting up the physical productQuickBooks · mintinglinking toFP-0260creatinglinkingShipStation · component productqueuedBoth run on their own. You can leave this screen.
Setting up stoppedQuickBooks · FP-0260linkedShipStation · weight read back as 0 ozneeds youIt will not retry on its own.
Tag each image with the role the generator reads. Practised order for the channel set: main → front → back → Supplement Facts → benefits → lifestyle → size → additional (MR-030). The free-text label under each image is its alt text.
Base images
v1
Vox “Cognitive Complex” — original launch formula
Everything on this tab belongs to this version. Switch versions in the header.
Copied from the source formula when the version was created, then this version's own. Labels take small liberties with wording, so edits here never reach the formula or the other products on it.
Notes 2
Anything about this product worth the next person knowing — a supplier conversation, a packaging change, why a measurement is what it is. Product-level, so a note stays put when the version toggle moves.
Dana Whitfield2026-08-21 11:38
eBay listing L-202 is holding on copy approval because the v2 panel names Alpha-GPC and the marketing blurb still reads like v1. Rewrite is with Marc.
Paul2026-06-30 09:05
Legacy import from the old sheet. The 1-pack eBay listing predates the catalog product, which is why L-198 carries no batch and no approved price.
Channel listings
No listings yet.
Channel listings
1 needs a person (attention: one listing is waiting on someone)
These already exist. Setup being incomplete does not retire them — it stops new ones being built, which is why Create listings… is off. Anything a listing is waiting on is named on its own row; it is not counted anywhere above, because it is not a fact about the catalog record.
Role is the structured label the image pipeline reads (practised order: main → front → back → Supplement Facts → benefits → lifestyle → size → additional, MR-030). The free-text label doubles as alt text and as prompt context.
Design notes — catalog product · setup & gaps
MR-066, built on MR-039 (v6) · fixtures CP-0102, and since MR-348 CP-0151 and CP-0152 · base art from mockups/sample-images/memopryl-base-images/
State 1 opens on CP-0119 (MR-389)
Memopryl is complete (RI-769): the product record shows its front image, its weight and three listings, and now opens on Setup complete. So 1 · Things need you opens, when the link names no product, on CP-0119 — the create form’s collagen example, which really has no front image and no weight. States 2–5 still open on CP-0102, because the QuickBooks decision is drawn there alone (P90). The product is now always written to the link (&cp=), so a reload keeps the one you picked; pick CP-0102 on state 1 and you see it rewound to before those two were supplied.
The drawer is a module now (MR-386)
This screen no longer draws the drawer; it mounts _setup-drawer.js, which the create form and the product record mount too, since Paul asked for the drawer inside both (2026-09-14). The harness still drives it: the state, the product and the QuickBooks path ride in the URL exactly as before. The gap and settled rows are computed from facts rather than drawn per product (RI-758), so the counts that used to be typed per fixture are derived — which corrected one: CP-0102’s caption said 2 of 10 and there are eight items. The weight row’s fix read Edit in a drawer and opened the Categories drawer; it is Open SF-0007 and goes to the formula that owns the weight. Checked by comparing all 35 harness states’ text before and after: those two lines are the only difference. Untick every Active mark on the panel and the drawer’s row appears, as before.
State 4 · ShipStation needs you (MR-385)
The running ShipStation card promised this state and nothing drew it. It said the component is an exact match on a SKU we minted ourselves, so there is never a decision here — only a success or a failure worth naming. Paul, 2026-09-14, asked for ShipStation issues to show wherever the mint states do, because ShipStation is minted at the same time as QuickBooks. So the failure is named: the QuickBooks item is linked, ShipStation answered OK, and the read-back found a different weight — 0 oz stored against 4.8 oz sent (RI-756).
Why that failure and not another. It is the one the ShipStation records already say happens: ShipStation keeps a field it quietly discarded and still answers OK, so a write is proven only by reading it back (RI-241). And weight is the field that costs money, because a bundle rates its label from its components’ weights (RI-239). A sign-in or duplicate-SKU failure was not drawn: neither has a measurement behind it for this write.
What it looks like: the run bar stops, amber, with QuickBooks linked beside ShipStation needs you; the header and rail chips say ShipStation needs you; the ShipStation SKU field reads did not read back; and the drawer keeps the QuickBooks card settled while the ShipStation card shows the four beats with Prove stopped, a sent-versus-stored table and Send the weight again. Listing stays blocked. The states are numbered 1–5 now; All complete is 5.
Sourcing decides what readiness asks for (MR-348)
Every catalog product now carries Sourcing, set once when it is created and shown read-only on Identity: Labeled by us (our label on a formula we hold) or Arrives finished (already labeled or branded when it arrives). A Product switch on the harness bar sits beside the three states and combines with each of them: CP-0102 Memopryl (labeled by us), CP-0151 Complexion MD (arrives finished, no formula, a cream) and CP-0152 Zero Air OG Essentials (arrives finished, a hard good).
Labeled by us is unchanged, with one addition: a Stock in line on the QuickBooks card naming the raw → finished transfer from RW-0003BL, so the raw stage the other path drops can be seen here to compare against. Moving stock is still warehouse work outside the job (QUICKBOOKS-FP-SETUP.md §8, RI-373).
Arrives finished drops the raw stage entirely. No RW SKU on Specs, no transfer: the same line reads received straight into the FP SKU · no RW SKU. The goods come in already labeled, so there is never unlabeled stock for a raw item to hold. The RW field is removed rather than shown as “none” — a field that can never hold a value is the raw stage drawn again.
No source formula is not a gap. Linking one is optional for a product that arrives finished (worth it only when the same formula is also sold under a label we apply), so the settled list says None linked instead of blocking. The facts a formula would have supplied become the product’s own rows — form, unit, weight, package dimensions and, unless it is a hard good, the ingredient list and current batch — and they are edited on the product’s Specs tab. That is where the Unit weight gap’s fix goes, instead of SF-0007’s drawer.
A hard good has no ingredient, panel, batch or COA rows at all, and the facts module beside the tabs stands down. Showing them as “not applicable” would read as facts that exist and are missing.
The batch is the product’s own when goods arrive finished, because they are received into the FP SKU rather than transferred out of a formula’s raw stock — so CP-0151’s lot, expiry, receipt and COA sit on its Specs tab.
Fixture provenance. Paul named Complexion MD and Zero Air; every number on them is illustrative — SKUs, weights, dimensions, ingredients, lot and PO. Neither fixture has a UPC, unit cost, benefits, categories, images, notes or listings, so those rows and modules are empty rather than invented. All three products show the same two gaps (front image, unit weight) on purpose, so the only difference between them is who owns the fact.
A readiness fix that opens a tab now closes the drawer first. Before, Add the front image switched the tab underneath an open drawer and nothing visibly happened.
The question this file exists to answer
The missing-items view had no home. It lived as a harness state inside catalog-product-create.html with no route to it from the product, and it was carrying two jobs that do not resemble each other. One surface is built here and moved between three placements — a tab, its own screen, a drawer — from the harness bar. It is moved, never copied, so no placement can look better for having been rebuilt and none of them can drift.
The split: a shopping list and two machines
The old panel was seven rows that looked alike and behaved in two ways. Waiting on someone are facts we must be given — an image, a weight, a barcode. Each is simply there or not; nothing is running. System records are two automatic jobs that check before they create, stop only when there is a real decision, and leave proof. Those have a lifecycle — checked · you decided · created · proved — that a table cell cannot hold, and the second is downstream of the first, which a flat row list cannot say either. So they are cards with the four beats drawn on them, and the beats are what makes the difference visible: QuickBooks reads created — not needed, adopted, ShipStation reads creating — failed 09:14.
ShipStation appears here for the first time. It was on neither screen before, yet QUICKBOOKS-FP-SETUP.md §6a names the exact state this fixture is in — QuickBooks linked, ShipStation pending — as real and retryable. One shared row could never have shown it.
The optional band is a band, not a colour. UPC, unit cost, benefit tags and gift eligibility block nothing, so they sit under a rule that says so and stop competing for alarm with the one row that does block.
✓ and ✗ on Identity
QB FP SKU and the new ShipStation SKU sit side by side, each carrying its own mark, and both are read-only — neither is a value anyone types. The ✗ is a link straight to this surface, which is one of four ways in; the header chip, the rail chip and the empty listings block are the other three, and all four are the same act.
What “attention” is allowed to mean here
On the catalog product record, “attention” means setup and nothing else (Paul, 2026-09-02). CP-0102 used to read “3 attention” here and “Ready to list” on the create screen, because the 3 were listing-level — L-202 awaiting content approval and two more — while readiness was clear. Two counters, two meanings, one word.
The first fix was to label both and show them side by side. That was wrong. A marketplace problem is not a fact about the catalog record, and once both live here the number on this screen can never be trusted to mean one thing. So the listing-level signals are gone from this page entirely — the rail chip and the header bell both. One counter remains, 2 things missing, and it counts setup.
Listing problems get a column, not a counter (Paul, same day). The Channel listings module at the bottom gains a Needs a person column, so a listing’s outstanding work is named on the listing’s own row — L-202 is waiting on copy approval, the other three are waiting on nothing. In context, next to the account, the SKU and the state, where it can actually be acted on.
That is strictly better than the bell it replaces. A counter in the header says three and makes you go hunting; a column says which one, and what for. It also cannot be confused with readiness, because it is inside the listings module rather than beside the product’s name.
The gate bites on making new listings, not on the ones that exist
The first draft emptied this module entirely, on the reasoning that an unready product cannot have listings. That was too strong. Setup can lapse after listings are live — a ShipStation record is lost, a front image is deleted — and nothing about that retires four listings that are already on eBay. So the existing listings stand and are readable, Create listings… is disabled with the reason, and the module says which rule is doing what.
Two fixture corrections
Two, not three. The count is honest rather than made to match the old chip: a missing front image and a ShipStation record that has not been created. catalog-product-edit-v6.html’s own design notes already flagged the missing front — memopryl-.webp is a byte-identical duplicate of the ingredients side.
Placement A is given its best shot
The product module is half the container by design, with supplement facts beside it, and a readiness table does not fit in half. So while Setup is the active tab the module spans both work columns and supplement facts stands down. A strawman would decide the comparison rather than inform it.
The settled state, and what it decides
Three states on the harness bar, and since MR-348 three products beside them. Every variant is in the DOM and one CSS rule per axis picks between them, with only the pieces that genuinely differ doubled — so the mid-flight and settled cases can never describe two different screens.
The checklist stays visible when it is clear. Following the precedent MR-056 already set on the create screen: it is the evidence that each thing was checked, not a badge that checking finished. A screen that empties itself on success throws away the answer to “was the weight ever verified?”.
The two system records collapse to one line each, opening on the proof. Not a judgement call — QUICKBOOKS-FP-SETUP.md §5.2 asks for exactly it: “once linked, the section collapses to a quiet line naming the item and when it was confirmed.” Built on <details>, so evidence-on-demand costs no script at all.
The four beats are the same four in both states, which is what makes them worth drawing. Settled reads created — retry 4, 09:31 and proved — read back, weight matched; the failure state reads creating — failed 09:14 under the same headings. The difference is legible before you read a word of prose.
Ready to list and a listing needing a person are independent, and the fixture proves it. In the settled state the product is listable, Create listings… is live, and L-202 is still waiting on copy approval in the module below. Two facts, two places, neither contaminating the other — which is the point of moving listing attention out of the header.
Bug the browser found and reading would not have
The fixture switch writes data-fix to <body>, so the delegated handler’s closest('[data-fix]') matched body on every click in the document and swallowed every handler after it — the placement toggle, all four ways in. Silent: no console error, the page simply stopped responding to one class of click. Now closest('button[data-fix]').
Active ingredients — none marked (MR-364)
Research reads only the panel rows marked Active (RI-719). On a product researched by Active ingredients, untick every row on the Specs tab and a blocking row appears in Needs you, the headline goes up by one, and it goes again as soon as one row is ticked (RI-723). It is not shown for Category or Guidance, and not for an empty panel, which is already its own gap. The settled Research by row carries the live count, 4 of 5 marked.
Open — needs Paul
Which placement. A keeps you on the product and costs one tab; B has the most room and costs a round trip; C is quickest to open and closes back to where you were, but at 920px the two system cards stack.
A tag that encodes a rule wants to be a field.no-amazon is in the fixture on purpose and it is the one that will break the model first: it is not a label, it is an instruction to a channel, and the moment anything downstream reads it the catch-all has become a schema nobody designed. The question is not whether to remove it — it is what the trigger is for promoting a tag to a real field, and who watches for it. Nothing is blocked today; nothing reads tags at all.
The scope model
Version-scoping is per field, not per tab, and one mark carries it: v1 plus a heavy left rule means the field belongs to the version selected in the brand strip. No mark means product-level. The shared chip was removed on 2026-09-12 (MR-345, RI-645) — product-level is the normal case, so a mark on it distinguished nothing.
Sold for is removed here too (MR-345, RI-649), with the edit screen's reasoning: its values restated Benefits, and research now reads every benefit on the product. The full account is in catalog-product-edit-v6.html's notes.
Colour is now spent on version identity, and this is a deliberate reversal. The rule used to be “no colour for scope, keeping colour for status only”. But a sticker that reads v1 in one hue and v2 in another can be traced back to the toggle at a glance, which a uniform black chip could not. The hues are drawn from outside the semantic set — never green, amber or red — so they cannot be mistaken for status, and the status chip stays where it was, inside the toggle button. Each version’s hue is the same on its sticker and on its button, so the pressed button and the stickers it governs read as one object.
A tab now carries two axes, not one. The old rule was “a tab is never mixed”, meaning one scope per tab. That still holds for scope — everything on Specs is version-scoped. What is new is ownership: Physical & packaging and Source formula are shown here but owned by the source formula, so they render read-only with an SF-0007 ▸ mark and are edited in the formula’s own drawer. Filling a blank from here is not allowed either — one owner, one place. That holds only when there is a formula (MR-348): a product with none owns those facts, so they lose the mark and become editable here — still one owner, one place. Switching version flashes the Specs tab’s groups.
Benefits and gift eligibility sit on Identity because both are product-level. Benefits come from a managed list rather than free text, so the listing builder’s angle picker does not fill with near-duplicates; gift eligibility exists only because a freebie is named in marketing copy and imagery — otherwise it is just another product riding in a combo.
Benefits stopped being a word cloud (MR‑331). Every value in the system used to be drawn as a pill you toggled. That is readable at six and unreadable at sixty, and the list is administered — it grows without any screen being edited, so the six was never a ceiling. It is now chips for what is on the product, and a search for adding one, which is the same interaction at six and at six hundred. The control is _tagfield.js, shared with the create wizard and the setup gate, and it owns the vocabulary too: the pill row had been pasted into three screens and had already drifted — this screen offered six benefits, the create wizard offered seven, and one of that seven (Skin & Hair) was never a benefit at all but a Sold for value. A list held in one place cannot do that.
Benefits are not inherited from the source formula, and that was asked for and turned down (RI‑616). The tempting version is real: four products share SF‑0007, they share its ingredients, so they would plausibly share what it does — and the screen already reads Physical & packaging and Current batch from the formula under exactly that argument (for a product labeled by us; since MR-348 one that arrives finished holds both itself). It loses because those are facts about the thing; a benefit is a claim made about a label, and two products on one formula are sold on different claims on purpose. Inheritance would also need a per-product memory of every removal, or a benefit deleted here would come back on the formula's next edit. The formula has no Benefits field and gains none.
Tags moved to the rail, beside Categories. Two chip controls stacked in one form read as one crowded field, and these two are opposites: Benefits is closed, curated and feeds real machinery downstream; Tags is the open place for what nothing else asks. The rail is where loose classification already lives. What tags are for was the genuinely open question, and the old fixture answered it by accident: nootropic, focus, memory, capsules — four words that other fields already hold (Benefits, Form, and at the time Sold for). A field whose contents duplicate its neighbours has no job. What is actually left over is operational: bestseller, subscription, seasonal, heat-sensitive, no-amazon — how a product is traded, handled and positioned.
Tags are curated, and a product screen may still add one. They are a managed vocabulary like the other three — Settings holds the order, the usage counts and the delete guard — but typing a name the list does not have offers to add it, because a catch-all that can only be chosen from is not a catch-all. Adding is the only write the picker does: renaming and removing stay in Settings, which is MR‑328/MR‑329's lesson pointed the other way — a screen reads a vocabulary, only the admin governs it. Two things keep the list from filling with near-duplicates: the search folds punctuation and case, so typing Heat Sensitivefindsheat-sensitive rather than offering to create a twin of it; and an add says out loud that it was global and what value was stored, because a write that reaches every product should not look like filling in a field.
The pickers do not say how many products share a value (MR‑332). They did for one round. A count is showing the work, and on the Settings tab it is load-bearing — 4 products is what makes a delete safe to reason about, and it is what the delete guard reads. On a picker it is a number beside every row answering a question nobody has while choosing one, and because the search matches a row's tag as well as its name, carrying it also made 4 a search term. The rows are names. Show the act does not mean show every number you happen to be holding — which is worth keeping as the correction rather than quietly tidying away.
Layout
Top section is the brand and the version toggle, right-aligned — a second deliberate reversal of “the brand and nothing else”. The toggle governs the whole module (both Specs and Base images are version-scoped), so the module’s own header is where it belongs, and the strip now reads as one statement of context: Memopryl · editing v1. The tab row was the alternative and lost: it already carries three tabs and their scope chips, it wraps, and a toggle dropping to its own line reads as broken.
Supplement facts is always visible and sits beside the tab module, each taking half the container, so both stack to roughly equal height and channel listings ride higher.
The sticky page header keeps only what acts on the whole product — save, create listings, attention.
Field grids fill the container width; an individual field stays around 230–300px, so nothing stretches.
Notes sits full-width directly under supplement facts, above channel listings.
Channel listings sit full-width at the bottom, one tab per sales channel.
Notes
The same shared block that source-formula.html carries, lifted markup-and-CSS intact rather than re-drawn: a container with data-notes and an optional data-author holding [data-newnote], [data-addnote], [data-notelist] and an optional [data-ncount]. Every lookup is scoped to that container, so the two screens cannot collide and neither needs initialising.
It is product-level on purpose. A note is about these goods — a supplier conversation, a packaging change — and reading it should not depend on which version the toggle happens to be showing. The formula's log answers the same question one level up; this one does not repeat it.
The nav collapses to its icons
A toggle in the brand row drops the rail from 284px to 58px. Labels are hidden rather than removed, so the section order, the current-page rule and the not mocked yet stubs are all still there when it opens again — and the work column gains the width, which is what the collapse is for: the identity grid goes from two fields across to three.
While collapsed each link carries its label as a native title, set by the toggle and removed on expand. A CSS tooltip was the first attempt and it does not survive: .sb has overflow:hidden and its scroller has overflow-y:auto, which clips anything reaching past the 58px rail, and there is no honest way to have overflow visible on one axis only.
Open: the collapsed state is not remembered — no reload survives it, because this screen has no URL state to hang it on. Worth settling before this is copied to the other promoted mockups.
Supplement facts editor
Table and Markdown are two views of the same data. The markdown dialect reads Serving Size:, Servings Per Container: and Other Ingredients: as their own lines; a row prefixed with - nests under the blend above it, which is what the real MemoPryl label needs. Paste a whole panel, hit Save facts, and the table repopulates.
Open — needs Paul
① QB FP SKU scope. Built product-level per your instruction, but SAMPLE-DATA.md L27 files FP-0260 under “Version v1”, and the original wireframe gives v2 its own FP-0261. Either the fixture is wrong or the rule is.
② No front-of-bottle image.memopryl-.webp is a byte-identical duplicate of the ingredients side, so the base set has ingredients and instructions only. Delete the duplicate and drop the front in as memopryl-front.webp — this screen picks it up with no code change.
③ Linking a formula later (MR-348). An arrives-finished product may link a source formula, but no control for doing it is drawn — Specs just reads none linked. Unsettled: where the link is made, and what happens to the product’s own weight, dimensions and ingredient list when a formula that also carries them is linked.