Appearance
Desktop journey readiness — merchant onboarding to consumer discovery
Status
🟠 Assessment, 2026-08-20. Measured against the live Claude Design prototype project (633dc069-6df8-4408-b625-068907c60c33, list_files + SCREENS.md pulled 2026-08-20, round 30) and against the repo at a45b21f. No local design cache was read.
Target journey: merchant desktop onboarding → create Ganapati stall → configure Setu Card → publish → marketplace → consumer discovers the stall → consumer views and interacts. Driver: native distribution is blocked on DUNS, so the desktop path must carry the first merchant.
0 · The one-paragraph answer
The merchant half of this journey is fully designed and already built — but as the Expo/RNW product, not as DOM. The consumer half is designed only as far as discovery and ordering, and the marketplace that connects the two halves has three approved designs and zero implementation. The fastest unblock is not a new screen: it is mounting the existing RNW export at /app, which ADR-0028 already decided and specified. The genuine design gap is a consumer desktop tier, which does not exist in the design at all.
1 · Already designed and ready for implementation
Merchant desktop console — prototype/desktop-console/, 16 screens
Round 20 for the console; round 22 added the two the journey starts with. Every screen carries light + dark plus loading, error and empty states.
| Journey step | Design file | Notes |
|---|---|---|
| Welcome, sign up, sign in | Auth.dc.html | The front door desktop never had. The phone's mechanics unchanged (Google, email + password, email + 6-digit code, 24s resend); desktop adds both panes at once, Enter submits, one-paste code. |
| Onboarding | Onboarding.dc.html | The phone's flow one for one (type → name → brand → industry → location → slug → alerts → highlights → celebrate), plus a step rail and a live Setu Card preview. Individual path visibly shorter. No plan step by design. |
| Create the stall (catalogue) | Catalogue.dc.html | Built for a stall entering 1,400–1,500 idols in four weeks: keyboard-first entry row, sticky attribute picks, inline-editable dense table, multi-select bulk edit. |
| Configure the Setu Card | CardEditor.dc.html | Section registry beside a live preview; writes the same override row the phone editor writes. |
| Publish / share | QRTools.dc.html | The one code, at print size, from the workspace slug. |
| Run the orders | Collections.dc.html, Payments.dc.html, ScanCollect.dc.html | Day-axis order book with multi-select and keyboard traversal; money passbook; counter station. |
| Rest of console | Home.dc.html, Messages.dc.html, Analytics.dc.html, Banking.dc.html, PlanBilling.dc.html, Profile.dc.html, Settings.dc.html, Notifications.dc.html |
Consumer marketplace desktop — prototype/marketplace/, 3 screens
Public, indexed, and open browsing is the hard rule: browse, search, filter, open a stall and open a listing all work with no account. Registration is action-triggered and inline.
| Journey step | Design file | Notes |
|---|---|---|
| Discovery | Discover.dc.html | Round 29 added it in front of Browse: resolves typed words into one of five outcomes (category, business, listing, place, demand nobody serves), then hands off to the indexed pages. Widening named rings, so an endless scroll never quietly changes subject. |
| Browse and search | Browse.dc.html | Category-in-a-city listing page: persistent left facet rail with live counts, crawlable /page/n links, four-column photo-dominant grid. States: default, no shops in area, no results for filters, no search match, loading, error. |
| Listing detail | Item.dc.html | The transaction gateway. primaryCta(vendor) decides the CTA, so a stall without payments shows Call and Message and no order control. Carries the inline consumer registration with a "Held for you" block so intent survives the interruption. |
Public Setu Card — designed and already built
prototype/setu-card/{SetuCard,CatalogueSection,ItemDetail,PublicCatalogue,Featured}.dc.html. Live in apps/web at /:slug/setu-card, with /:slug/order and /:slug/order/:orderId/:reference already implemented.
2 · Missing or incomplete
⚠⚠ CORRECTED 2026-08-20, SAME DAY: THIS SECTION WAS WRONG, AND WRONG IN THE EXPENSIVE DIRECTION
It originally read "there is no consumer desktop tier" and listed six missing surfaces, the order code among them, calling it "the one that breaks a finished transaction". Measured after the owner challenged it: the consumer product already ships to desktop and the order code is built.
screen-conformance.json records the consumer tier at 10 of 11 built — consumer-home, item-feed, vendor-feed, item-view, vendor-view, consumer-chats, consumer-notifications, order-code (OrderCodeScreen), account and featured, every one reachable: true. Only scan-verify is unbuilt. resolveEntryRoute routes consumers. And because the consumer tier lives in the universal Expo app, expo export -p web emits all of it: consumer/order-code.html is 29,456 bytes, mounted at /app/consumer/order-code by this same change.
So the error was reading a DESIGN-PROJECT scoping note as a statement about the PRODUCT.VENDOR-PARITY.md §4 says "Saved, orders, account — out of scope for desktop", and I repeated it as settled. It is a note about which surfaces the marketplace DOM pages carry, authored design-side and never put to the owner — and read as product scope it contradicts CLAUDE.md's ENFORCED cross-platform-parity standard, whose exception path the owner retired on 2026-08-02. A desktop user must have no feature limitation, and structurally they do not: one Expo codebase reaches Android, iOS and web together, so parity here holds by construction rather than by effort.
⚠ The generalisable lesson, which is this repo's own most-repeated defect: a written scoping line in a document that is otherwise authoritative is still only a hypothesis about the product. I verified the design registry meticulously and then took a product claim from it on trust. Establish which artifact is authoritative for the question you are actually asking — the design project is authoritative for what a screen looks like, never for what the repo has built.
What is genuinely open (the corrected list)
| Item | Status |
|---|---|
scan-verify | The one unbuilt consumer screen (1 of 11). |
| Anonymous DOM buyer → live order code | A registered consumer has order-code on every surface. An anonymous marketplace buyer has only the confirmation URL (/:slug/order/:orderId/:reference), which is a bearer token and does carry the reference. Whether that page should also present a live re-minted code is a real design question, and the only consumer-desktop item still worth a prompt. |
DOM marketplace vs /app division of labour | Decision, below. |
The division of labour that satisfies "no platform limitations" without a second implementation:/app carries the full consumer feature set on every surface including desktop; the DOM marketplace stays the public, crawlable discovery front door and hands off to /app for anything account-bound. Duplicating account surfaces into the DOM marketplace would be a second consumer implementation — the same mistake ADR-0019 refuses for the card ("one renderer, always DOM") and the same conflict as the DOM merchant console.
The original (incorrect) list, kept because deleting a wrong claim hides that it was made
It named these as missing desktop surfaces: order code, account and profile, order list and detail, chats, notifications, saved/favourites, and a standalone consumer sign-in. All but the last two are built and shipping to desktop via /app. Retained per this repo's rule that a superseded record is banner-stamped, never edited away.
Superseded original text
All 13 prototype/consumer/ screens are marked mobile only in the design registry. That is true of the DESIGN and false of the PRODUCT. The list that followed was:
| Missing consumer desktop surface | Consequence for the Ganapati journey |
|---|---|
Order code / collect leg (OrderCode.dc.html is mobile only) | The one that breaks a finished transaction. The buyer has no way to present a collectable code from a desktop. |
| Consumer account and profile | A registered consumer cannot manage anything they created. |
| Consumer order list and detail | No "my orders" on desktop, only the single bearer-token confirmation URL. |
| Consumer chats | The merchant console has a two-pane inbox; the consumer has no desktop reply surface. |
| Consumer notifications | No desktop delivery for "your idol is ready". |
| Saved / favourites surface | Anonymous device-save is designed inside the marketplace, but nothing lists what was saved. |
| A standalone consumer sign-in entry | Sign-in exists only inline inside a listing page. A returning consumer landing on qrsetu.com has no door. |
Round-30 design content the schema cannot support
- Ratings. Round 30 gave every marketplace card a rating chip and a quoted latest review from a
RATINGSrecord inconsumer-data.js. There is no ratings table in this repo. The design notes this reverses the earlier refusal (QRS-576) on the grounds that the opinions always existed and only the table was missing, which is true, and the table is still missing. Rating chips must be absent, never faked. - Photographs. Both marketplace grids are explicitly photograph-dominant. See §3(d).
3 · Architecture and backend dependencies, and the real conflicts
(a) ⚠ CONFLICT — the desktop console asks for a second merchant implementation
SCREENS.md states the desktop console is "a SEPARATE route group in apps/web, DOM/React over shadcn/Radix primitives … It is not React Native Web and not a scaled phone screen."ADR-0011 says the merchant product is one universal Expo codebase shipping to Android native, iOS native and responsive web via RNW.
So the design asks for a 16-screen DOM rebuild of a merchant product that already exists and already runs in a browser. Measured cost floor, today:
apps/web/src/ui/contains 2 components (Button,TextField) pluscn.apps/web/package.jsonhas zero radix or shadcn dependencies.apps/webhas no authentication of any kind — no Supabase auth client, no session, no protected route. The desktop console needs all of it; the RNW app already has Google sign-in live.
This is not a one-day item and should not be attempted as one. The conflict deserves a deliberate resolution later (density, keyboard flow and multi-select are genuine desktop advantages RNW will not match), but it is a wave of work.
Resolution for the deadline, and it is already the decided architecture: mount the existing RNW export at /app. ADR-0028 specifies exactly this — "the assets directory is apps/web/build/client with apps/mobile/dist placed at /app. Two artifacts, one origin." That yields merchant desktop onboarding, stall creation, card editing, orders and payments with no new screens, because responsive web is one of the three R1 surfaces and is already built.
⚠ (b) Measured while implementing (a): EXPO_BASE_URL alone does not mount the app
Setting EXPO_BASE_URL=/app on expo export -p web exits 0 and produces a root-relative bundle: 0 app-prefixed references and 3 root /_expo/ references in dist/index.html. The CLI derives that variable from experiments.baseUrl in the app config during bundling; supplying it from outside does not drive the HTML rewriting. So a config change is genuinely required, and it carries a real blast radius, because e2e/ and the run-mobile driver both serve dist/ at root and would 404 on every asset.
The chosen shape: an app.config.js that spreads app.json and adds experiments.baseUrl only when an env var is set. Local, e2e and the driver stay root-relative and unchanged; the deploy sets the var. app.json remains the version SSOT, so version:set and check:version are unaffected. Recorded as QRS-779.
(c) ✅ The marketplace backend is ready — the part that can ship properly
Every read the three marketplace screens need is live and anon-granted, in the committed migration 20260818120000_v2_consumer_discovery_read_path.sql:
| RPC | Signature |
|---|---|
get_consumer_item_feed | (p_area text, p_sort text, p_filters jsonb, p_page integer) |
get_consumer_vendor_feed | (p_area text, p_sort text) |
get_consumer_item | (p_item_id uuid) |
get_consumer_vendor | (p_slug text) |
get_states / get_cities | () / (p_state_key text) |
All are grant execute … to anon, authenticated, which is what makes open browsing possible with no session. packages/data/src/consumer/ is Supabase-backed and exports CONSUMER_RPC, CONSUMER_SORTS and CONSUMER_FILTER_THRESHOLD — the threshold is re-exported from the seam precisely so the client cannot invent a second one.
(d) ⚠ No public media URL exists, so a photograph-led marketplace has no photographs
packages/data/src/mediaUrl.ts fails closed and returns null until setPublicMediaBaseUrl() is called, which nothing does, because no bucket is provisioned. get_public_catalogue projects storage_key, never a URL. For a marketplace selling ₹45,000 idols this is commercially the largest single gap in the journey — nobody buys an idol from a line of text. It is a wave of work that has not shipped, not a bug in a caller, and it should be sequenced ahead of marketplace polish.
(e) The promotion layer must render nothing
The marketplace design carries ten promo slots and registers them in the Ad Manager's PLACEMENTS. ADR-0004's promo_slot fails closed forever pending a compliance_profile column that does not exist. Shipping a live resolver risks a compliance-restricted vertical carrying an ad it legally cannot. Do not implement the promotion layer; the slot renders nothing, the same posture the card manifest already takes.
(f) URL taxonomy needs sign-off before the first crawl
marketplace is already a reserved slug (20260808110000_v2_reserved_slugs.sql), so there is no namespace collision. But the taxonomy is marked proposed, permanent once indexed: /marketplace/<category>/<city>, /marketplace/<category>/<city>/<area> and /page/<n> as crawlable paths; facets as noindex parameters with a canonical back to the path; a listing at /<slug>/item/<item-slug> as the card's sibling. ADR-0028 governs first segments, and the vendor slug namespace is flat and at the root, so a first segment spent is spent permanently. Confirm before the first crawl, not after.
4 · The exact design delta
Everything the target journey needs on the merchant side is designed. The delta is entirely consumer-desktop, plus two data-truth corrections:
| # | Delta | Why this journey needs it |
|---|---|---|
❌ WITHDRAWN — order-code is built and mounted at /app/consumer/order-code. | ||
| ❌ WITHDRAWN — all built in the consumer tier and shipping to desktop web via RNW. See the correction in §2. | ||
| D1a | Live order code for an ANONYMOUS marketplace buyer | The one survivor: an anonymous buyer holds a confirmation URL, not an /app session. |
| D9 | scan-verify | The single unbuilt consumer screen (1 of 11). |
| D7 | Rating-less marketplace card state | Round 30 assumed a ratings table that does not exist. |
| D8 | Image-less marketplace card state | No media pipeline, and the grids are photograph-dominant. |
D1, D7 and D8 are the ones that block implementation. D2–D6 can follow, because open browsing means the discovery and purchase path does not depend on them.
5 · Prompt for Claude Design — missing consumer desktop screens only
Send to the prototype project (633dc069-6df8-4408-b625-068907c60c33), not the design-system project. It deliberately asks for nothing that already exists: no marketplace redesign, no merchant console change, no mobile consumer change.
Copy-paste prompt
text
Add a CONSUMER DESKTOP surface to prototype/consumer-desktop/. This is new: all 13 screens in
prototype/consumer/ are mobile only, and the desktop marketplace (prototype/marketplace/) currently
ends at ordering, so a consumer who buys on a desktop has nowhere to go afterwards.
Do NOT redesign anything that exists. Do not touch prototype/marketplace/, prototype/consumer/,
prototype/desktop-console/ or prototype/setu-card/. Reuse their kits and data: read
../consumer/consumer-data.js and ../marketplace/market-kit.js, and match the shell language of
prototype/desktop-console/ (same chrome, same focus ring, same light plus dark) while remembering that
a consumer is not a merchant and has no workspace, no sidebar of business modules and no capabilities.
Screens, in priority order.
1. OrderCode.dc.html (HIGHEST PRIORITY, the only gap that breaks a finished transaction)
The desktop twin of prototype/consumer/OrderCode.dc.html. The buyer's half of the merchant's
Scan to collect. The code is re-minted on open and refreshed every few minutes, so a screenshot
taken earlier is refused later, and the screen must say so in plain words. Because a desktop is not
carried to a stall, the desktop version's primary job is TRANSFER: show the code large enough to be
read aloud or photographed, plus a print view and a "send to my phone" affordance. States: live code,
refreshing, expired and re-minted, order not yet payable, order already collected, error.
2. Auth.dc.html
A standalone consumer sign in and sign up door. Mechanics identical to
prototype/desktop-console/Auth.dc.html (Continue with Google, email plus password, email plus a six
digit code, 24 second resend, Enter submits, one paste fills the code). What differs is the framing:
this person owns no business, so the left pane must not promise merchant features. It must also carry
the "Held for you" continuity the marketplace listing page already uses, because a consumer arrives
here mid intent. States: sign up, sign in, code sent, verifying, error.
3. Orders.dc.html
My orders: a list plus a detail pane beside it, not over it, following the Collections two pane
pattern. Each row carries the reference in the platform's Crockford format, the stall, the item, both
status axes, what was paid and what is due at the stall. Detail opens the order code (screen 1).
States: has orders, one order, no orders yet, loading, error.
4. Saved.dc.html
What the marketplace saved. It must work for an ANONYMOUS visitor whose saves live on the device, and
state honestly that registering is what makes a save follow them to another device. Never a signup
wall. States: has saves, anonymous with saves, no saves, a saved piece since sold.
5. Chats.dc.html
Two pane, same shape as prototype/desktop-console/Messages.dc.html, from the consumer's side. It must
read the same chat-core.js the merchant thread reads. States: has conversations, no conversations,
blocked by the business.
6. Notifications.dc.html
The consumer's list. Order progress, a message, a stall update. Each individually mutable. States:
has notifications, all read, empty, error.
TWO DATA TRUTH CORRECTIONS to the existing marketplace, the only changes I am asking for outside the
new folder. Both are cases where round 30 drew something the platform cannot supply, and drawing it
anyway forces the build to either fake it or diverge.
A. RATINGS DO NOT EXIST. There is no ratings table in the platform and none is planned for this
release. Every rating chip, review count, quoted review, category average and aggregateRating in
Browse.dc.html, Discover.dc.html and Item.dc.html needs a designed ABSENT state: what the identity
row, the stall line, the answer panel and the listing trust block look like with no rating at all.
Not "New on QR setu", which still implies a scale. Nothing.
B. THERE ARE NO PHOTOGRAPHS YET. No media bucket is provisioned, so every image slot resolves to
nothing on day one, and both marketplace grids are photograph dominant. Design the no-image state
for the Browse grid cell, the Discover stream card and the Item listing gallery. It must not look
broken or like the stall's own photo failed, because a buyer reads a torn page icon as the vendor's
fault. Reserve the same box from the stored ratio so nothing reflows when photographs arrive.
Constraints that apply throughout.
- Open browsing is the hard rule and these screens do not weaken it. Discovery, browsing, viewing a
stall and viewing a listing stay fully usable with no account. Registration stays action triggered.
- There is no in app purchase or upgrade CTA anywhere in these screens.
- A capability the platform does not have must be absent, never shown disabled and never shown locked.
Locked is only for something a paid plan would unlock, and none of these are.
- DO NOT use em dashes or en dashes anywhere in generated copy, labels or examples. Use a comma, a
colon, parentheses, or two short sentences.
- Light and dark, plus loading, error and empty states on every screen.
- Responsive down to 390px verified by measurement, no horizontal overflow, touch targets reaching
44px through a hover:none breakpoint rather than by inflating desktop controls.
- Register every new screen in SCREENS.md in its own section, so the registry stays the only place a
screen list is maintained.6 · What is being implemented in parallel, and what is deliberately not
| Doing now | Why |
|---|---|
Mount the RNW export at /app | ADR-0028's decided shape; unblocks the whole merchant half with zero new screens. Blocked on §3(b), tracked as QRS-779. |
| Marketplace routes on the live consumer RPCs | The only journey step with a complete backend and no implementation. |
| Record the taxonomy decision before the first crawl | A spent first segment is permanent. |
| Deliberately not doing | Why |
|---|---|
| The 16-screen DOM desktop console | §3(a). A wave, not a sprint, and RNW already covers the journey. |
| The promotion layer | §3(e). Fails closed forever pending compliance_profile. |
| Rating chips | §2. No table. Absent, not faked. |
| Consumer desktop D2–D6 | Awaiting the §5 designs; open browsing means the purchase path does not need them. |
Related
- Consumer Marketplace Spec — the 2026-08-10 specification these screens were designed from. ⚠ Its status banner still reads "screens do not exist yet"; three now do.
- Screen conformance — the presence ledger. ⚠ It tracks 36 screens across
mobile-console,consumerandonboardingonly; the 16 desktop-console and 3 marketplace screens are absent, socheck:screensis blind to this entire assessment. - ADR-0028 — one origin,
/app, reserved first segments.