Everything you need to write the RA and the system spec for Lane B, and the one interface where your half meets mine.
Halehaku Maui, Family Farm Shop. That is their own name for themselves, off the window decal. It sits at mile marker 1 on the road to Hana, which makes it the last real stop before a long winding stretch, so tour vans pull in by arrangement with the drivers.
Tourists come through daily, see something, and ask for a website. There has never been one. People go home and cannot buy. That is the whole reason this project exists, and it is worth keeping in front of you, because it tells you who the portal is really for: not the shop, the person who already left.
The room is white walls and pale floors, and every bit of colour comes from the work hanging on them. The shop is already a design system. Neutral container, work supplies the colour.
She is an artist by default and by preference. In her own words, "I just want to paint a flower." She has built online stores before and quit, because the admin defeated her.
The single most useful line she said about the whole project:
"That's what I need is someone to make it simple because look how complicated I make it."
She also asked, three separate times and unprompted, to be taught to do it herself afterwards. That is not a nice to have. It is the deliverable she cares about most, and it is a hard design constraint on your lane: if it cannot be taught in one sitting, it is too complicated.
Her one stated condition on rebuilding at all is that it is secure. That is why payments and card data never touch what we build, and why that boundary is not negotiable and not a phase two thing. Checkout sits on a commerce backend behind us.
Juliet's son. Not a maker. He is organising this on his mother's behalf, and all client contact runs through me, so if you need something from the family, ask in Slack and I will ask.
The internal surface Juliet uses. She takes a photo of a shirt she just painted and wants it live on the storefront without asking anyone.
The storefront a visitor sees. It renders the catalog and does not own it.
One interface between us: the catalog contract. You write it, the public site reads it. Nothing else crosses the line, which is why the contract is the thing to get right before either of us builds much on top of it.
The first draft is in the requirements file. Below is that draft after reading it as the consumer, which is the only angle I can usefully add. Argue with it.
catalog
version contract version, not content version
generated_at ISO 8601
makers[]
slug stable, internal, safe to ship today
display_name nullable until the family confirms
credit_line nullable
bio nullable
products[]
id
maker slug
category silk | tshirts | original-art | oils | wall-hangings |
photography | woodwork | pottery
title
description editable by Juliet
images[] ordered, first is primary, uploadable by Juliet
url
width
height
status draft | published
acquire buy | inquire
custom bool
lead_time_days when custom. 12 for painted shirts, her own revision
one_of_a_kind bool
variant_display list | primary_with_note
variants[]
label "8.5x11 canvas", "2oz"
price nullable when acquire = inquire
fulfilment direct | dropship
available bool
maker is a record, not an enumEverything after slug is nullable. The family has not confirmed how each
maker wants to be credited, or even the spelling of one of their names, and nothing about
them ships unconfirmed. This change is what lets the public site organise by medium today
and take real names later as content, with no schema change on either side.
price is nullable, paired with acquireOriginal art is one of a kind and never repeated. Her instinct was to mark those "please inquire" rather than sell them through checkout, and that is still undecided. A non nullable price field is an invitation to seed a placeholder, and a placeholder price has a way of shipping as the real one.
variant_displayOn the oils she was specific: "I would only do the one ounce, and then underneath I'd say two ounce available at a different price. They just need one picture." The variants stay truthful with real prices. This hint tells the public site to render her way instead of printing a size table.
alt field, on purposeAlt text is generated on the public side from title, maker and category. She named three inputs. A fourth breaks the one thing she actually asked for.
status: draft | publishedOne toggle, so a half finished upload is not live the second she saves.
Her T-shirt rule collides with variants. She said: "if you just put one thing for T-shirts, and then I'll just upload different pictures." One listing, many photos. But T-shirts also have sizes, and a buyer has to choose which design, which makes the photo an axis rather than a gallery. So either images carry variant identity, or there is a second axis, or her rule means something narrower than it reads. This is the first real question for your spec, and it is a good one.
Lane B publishes catalog.json. Lane A fetches it. Not a shared database. No
credential crosses between us, you can ship a real file before you have a backend, and either
side can be rebuilt without touching the other.
They are being chased with the family. If something is not written down somewhere, it is not decided, and a sensible guess ships as a fact.
| # | Question | Blocks | Owner |
|---|---|---|---|
| 1 | The spelling of one maker's name. Two spellings appear in our own notes | Anything user visible | Nalu, with the family |
| 2 | The name of the fourth artist, and what they make | Catalog completeness | Nalu |
| 3 | Do the oils sell direct here at all? They sell wholesale through a third party today | Whether oils are a shop category or display only | The family |
| 4 | Original art: inquire only, or real checkout? | Whether
price is ever null in practice | The family |
| 5 | Shipping carriers, costs and timelines per product type | Fulfilment logic | Nalu |
| 6 | Do the makers want bios, and how does each want to be credited? | Public site copy, and whether maker needs a profile
record | Nalu, with the family |
| 7 | Who controls the domain | Launch, not build | Nalu |
One data source is locked and may stay locked: a second existing listings account behind a two factor check that has never cleared. If it does not open, that category's copy gets written from scratch rather than migrated. Build as though it will not arrive.
Checkout sits on a commerce backend. The portal manages catalog content only. This is the thing that lets us honestly tell her it is secure, so it is not a boundary to be revisited when something gets inconvenient.
Only a handful are on record and they sit with me. Not in the portal, not in test fixtures that could be mistaken for real, not in a screenshot.
Our own notes disagreed with each other once already about who is related to whom. Names, credits and relationships get checked with them before they appear anywhere.
I hold every client credential and all client contact. You should never need a real client account to work, and if it looks like you do, that is a design problem to raise rather than a login to request.
The hardest case in the catalog is the photographer: one source image fans out into originals plus prints across multiple sizes and multiple materials, and fulfilment splits by size, with large prints drop shipped and small ones shipped direct from the shop. That is a per variant property, not a per product one. If the schema handles him, it handles everyone, so it is worth modelling him first rather than last.