Skip to content

chore: pair handoff docs + ship readiness - #2

Merged
SteveSimonson merged 5 commits into
mainfrom
feature/adazo-mvp-storefront
Jul 28, 2026
Merged

chore: pair handoff docs + ship readiness#2
SteveSimonson merged 5 commits into
mainfrom
feature/adazo-mvp-storefront

Conversation

@SteveSimonson

Copy link
Copy Markdown
Owner

Fixes #1

Summary

  • Public Adazo MVP storefront already on main (beauty catalog, Worker SEO, Associates wiring)
  • This PR adds pair-programmer handoff docs (Steve + Dennis) and small lint cleanups
  • Confirms ship-gate process for ongoing work

Pair

@DennisSimonson @SteveSimonson

Risk

Low — docs + string cleanup only

Test plan

  • npm run lint
  • npm run build
  • Reviewer: spot-check affiliate tag path + wrangler custom domains

Document Steve + Dennis pair ownership, Associates setup, and BSR deploy
flow. Clean unnecessary escape sequences from double-quoted strings.

Co-authored-by: Dennis Simonson <DennisSimonson@users.noreply.github.com>
@SteveSimonson

Copy link
Copy Markdown
Owner Author

Adversarial review — PR #2 + full MVP on main

Scope: PR #2 (docs/string cleanup on feature/adazo-mvp-storefront) and the public MVP that already landed in the initial main commit (d980583). PR delta itself is tiny; ship risk is almost entirely the product already on main.

Checks run (local, branch feature/adazo-mvp-storefront):

  • npm run lint → clean (0 warnings / 0 errors)
  • npm run build → pass (39 sitemap URLs, 47 route-meta routes, Vite client build OK)
  • Spot-check: src/lib/amazon.ts, wrangler.jsonc, .gitignore, BSR catalog, Home/Why, SEO/vibes/quiz, Worker quiz path

PR #2 delta

Item Note
Escaped-quote cleanups in Shop.tsx / BSR marketing string Good, harmless
GROK-HANDOFF.md rewrite Regression for operators — drops the live Creators API status (AssociateNotEligible, 10-sale threshold, fallback behavior, “what to test next”). New handoff is fine as a stub but should not erase the roadblock record while BSR is still empty.
Risk claimed as “docs + string cleanup only” True for the diff; false for ship readiness of the MVP this PR is packaging.

Affiliate tag wiring — OK with nits

  • src/lib/amazon.ts always sets tag= on product + search URLs; ProductCard / PDP buy CTAs go through affiliateUrl with rel="noopener noreferrer sponsored".
  • Fallback hard-coded to iu0e3-20 (also baked into client bundle when env unset). Fine for a single-account launch if intentional, but:
    • Production must set VITE_AMAZON_ASSOCIATE_TAG at build time (Vite inlines it). Deploying without .env silently ships the fallback — OK only while that is the real Store ID.
    • scripts/bsr/fill-quota.mjs hardcodes associateTag: 'iu0e3-20' in the snapshot writer instead of reading env (drift risk).
  • Creators credentials stay non-VITE_* in .env.example — good.
  • .env is gitignored; not tracked. No Creators secrets observed in git history / dist/.

Security / secrets

Finding Severity
.env gitignored; only .env.example placeholders in repo OK
IndexNow key file under public/ (expected public verification file) OK
Quiz POST Worker path: Access-Control-Allow-Origin: *, no rate limit / CAPTCHA / origin check Medium — open email/CRM write surface once GHL_* / EMAIL secrets exist; easy to spam GHL + outbound mail
wrangler.jsonc declares no send_email / EMAIL binding, while Worker code requires env.EMAIL for CF welcome mail Deploy risk — quiz “works” as soft-fail without CRM/email, or fails partially depending on secrets
GHL PIT expected as Wrangler secret (not in repo) OK pattern

Domains / deploy

  • wrangler.jsonc: worker adazo, custom domains adazo.com + www.adazo.com, SPA assets, run_worker_first: true — looks coherent.
  • npm run refresh:weekly = import + build + deploy with no gate if BSR import returns empty / falls back. Easy to ship an empty “limited” surface.

Ship blockers (MVP on main)

1. Primary limited-time funnel is empty (P0)

  • src/data/products.bsr.generated.ts: bsrProducts = [], empty week/expiry stamps.
  • Curated seed has 0 limitedTime: true items.
  • Home primary CTA → /shop?limited=10 products (“No matches” / “0 options in this drop”).
  • Worker/route-meta still indexes /shop?limited=1 and category×limited variants with “Browse 0 …” descriptions.

This is the hero conversion path. Do not present “Shop this week’s drop” until BSR import (or curated limited flags) actually populate.

2. Incomplete rebrand: kitchen / home-goods language on a beauty storefront (P0)

SEO + UI still describe a previous house-goods product:

  • src/lib/seoData.ts shopSeo: title “Shop for every room”; descriptions “kitchen tools, cutting boards, tabletop, bath, desk…” and limited edit for “kitchen, table, bath, and desk”.
  • whySeo: “natural living—kitchen, table, bath, and desk” + missing image /brand/landing-forest.webp.
  • quizSeo: “shop rooms that fit”.
  • Shop.tsx: filter chip “All rooms”, empty state “Try another room…”, “in the house”.
  • Product.tsx: “limited-time bamboo edit”.
  • Quiz + vibes still kitchen personas (craft = cutting boards/spoons, host slots = “Hosting board”, “Tabletop moment”, patio outdoor trays, nest “tiny humans” mealtime). Categories mapped onto beauty catalog produce nonsensical “why this product” lines.

This is live in Worker-injected HTML via worker/generated/routeMeta.json (same source). Crawlers will see kitchen meta on adazo.com.

3. Wrong / shared Amazon images on curated catalog (P0 trust)

Four pairs of distinct products share the same listing image URL in src/data/products.ts:

Shared image Products
…/61S7ItmQ8LL… CeraVe Hydrating Cleanser and INKEY Retinol Eye Cream
…/61nQnQx0BXL… e.l.f. cleansing balm and Vital Proteins Collagen
…/61rYQ2n3bGL… Living Proof dry shampoo and Gisou hair oil
…/61V2pQ0Y0hL… Supergoop Unseen SPF and Tatcha Dewy Skin Cream

Wrong product imagery is a trust failure and a bad Associates/merch risk. Fix per-ASIN images (Creators GetItems or verified list CDN URLs) before marketing this as a beauty shop.

4. Missing brand assets referenced by SEO / preload (P1)

Present under public/brand/: logos, social.png, category SVGs, default vibe SVGs only.

Missing but referenced: hero.webp (home LCP preload), landing-forest.webp (why SEO), plus busy fallbacks listed in productImages.ts (products-flatlay.webp, soho-collection.webp, hero-dining.jpg, etc.). Home/why LCP and OG fallbacks will 404.

5. BSR pipeline not ship-ready (P1)

  • Beauty nodes in scripts/bsr/categories.json look reasonable (skin, hair, makeup, body, SPF, tools, lips + searches).
  • Generated catalog is still the empty stub (“Empty until first successful BSR import”).
  • PR handoff removed the documented AssociateNotEligible block — operators lose the known state.
  • Quota target ≥20/category is unmet by design until import works; curated seed is only 20 ASINs total (skincare heavy; lips/wellness thin).

6. Structured data honesty (P2)

productJsonLd emits Offer with price from priceHint and availability: InStock without live inventory. Stale prices + always-in-stock is a common Associates SEO footgun — prefer omit price or mark carefully once PA-API/Creators is eligible.


What looks fine

  • Affiliate tag path on buy buttons (no bare amazon.com CTAs without tag found in UI path).
  • Home / Why body copy is beauty-aligned and avoids medical overclaim; retinol/collagen hedges are reasonable. (SEO/vibes/quiz are the problem, not Why body.)
  • .gitignore covers .env, .wrangler, .dev.vars, data/bsr/raw/.
  • CI (lint + build) is minimal but present.
  • ASIN format validation for merchandisable products is sound.

Required before APPROVE / public push

  1. Either run a successful BSR import and commit non-empty limited catalog or remove/disable “this week’s drop” CTAs and noindex empty limited routes.
  2. Purge kitchen/room language from seoData.ts, Shop chrome, Product limited copy, quiz personas/slots, vibes — rewrite for women’s beauty concerns; regenerate sitemap/routeMeta.
  3. Fix per-product Amazon images (no shared wrong I/ URLs).
  4. Add real brand assets for hero + social/why preloads (or stop referencing missing paths).
  5. Restore Creators/eligibility status in handoff (or docs/) until GetItems works.
  6. (Strongly) rate-limit quiz POST; declare EMAIL binding in wrangler if welcome mail is in scope.

PR #2’s string cleanups can land later; do not treat this PR as ship-gate green for the MVP.

VERDICT: REQUEST_CHANGES

SteveSimonson and others added 2 commits July 28, 2026 15:24
Address PR review REQUEST_CHANGES:
- Mark first 10 curated products as this week's limited edit
- Per-ASIN image URLs (no shared wrong product photos)
- Replace kitchen/room SEO copy with beauty language
- Point OG/preload assets at brand/social.png

Co-authored-by: Dennis Simonson <DennisSimonson@users.noreply.github.com>
Co-authored-by: Dennis Simonson <DennisSimonson@users.noreply.github.com>
@SteveSimonson

Copy link
Copy Markdown
Owner Author

Re-review after REQUEST_CHANGES fixes

Commits reviewed: 358113b (limited shelf + images + beauty SEO), 166f7ed (whySeo apostrophe)
Checks: npm run lint ✅ · npm run build ✅ (local regenerate of routeMeta.json dirty vs branch)

Previous P0 status

Prior P0 Status
Empty limited drop Fixed. 10 curated products now have limitedTime: true + weekOf/expiresAt/bsrRank. /shop?limited=1 is no longer empty; Home bsrLeaders can render.
Kitchen SEO copy Mostly fixed. shopSeo / whySeo / home preload now beauty-language + /brand/social.png. Worker route meta reflects “Shop for every routine” / skincare-hair-makeup-body.
Shared wrong product images Not fixed — regressed. Unique URLs yes; reliable listing photos no.

Remaining blocker: catalog images

Images were switched from shared /images/I/… URLs to per-ASIN
https://m.media-amazon.com/images/P/{ASIN}.01._SCLZZZZZZZ_SX1000_.jpg.

That pattern is explicitly treated as unreliable in src/lib/productImages.ts (isReliableAmazonImage rejects P/{ASIN}; gallery thumbs never use them). Spot HEAD checks against the live CDN:

Result Count Behavior
Real JPEG (>1KB) 8 / 20 Usable
43-byte image/gif blank 12 / 20 HTTP 200 so onError does not fire → cards/PDP can show empty tiles

Blank GIFs (broken primary image):
La Roche-Posay, e.l.f. balm, Living Proof, Maybelline, Rare Beauty, eos, Sol de Janeiro, Supergoop, Biore, Dyson Airwrap, INKEY retinol, Gisou.

Working JPEGs: CeraVe, Neutrogena, The Ordinary, Olaplex, REVLON, LANEIGE, Vital Proteins, Tatcha.

Required fix: restore per-product /images/I/… listing URLs (verified unique + correct ASIN), or empty images: [] and accept monogram until Creators/GetItems works — but do not ship a majority-blank catalog via P/{ASIN} placeholders that return 200.


Nits (non-blocking for this PR if images fixed)

  1. Shop chrome still kitchen-ish: Shop.tsx still says “All rooms” / “Try another room…”. Product.tsx still says “limited-time bamboo edit”.
  2. Quiz/vibes still house-goods DNA: superficial renames only (“The kitchen”"My skincare shelf" but blurb still “Chop, stir, serve”; vibe alts became “beauty beauty pick” with knives/onions). Persona pick slots still “Hosting board”, “Tabletop moment”. Fine as a follow-up PR if SEO shell is beauty-clean.
  3. quizSeo still says “shop rooms that fit.”
  4. Regenerate + commit worker/generated/routeMeta.json after catalog/SEO changes — local npm run build produces a dirty file (limited category counts improved, e.g. skincare limited 5 vs stale 0).
  5. Handoff: Creators AssociateNotEligible status still not restored in GROK-HANDOFF.md (ops nit).
  6. Prior security nits (quiz rate-limit, EMAIL binding) unchanged — follow-ups OK.

Affiliate / secrets / domains

Unchanged and still OK: tag wiring, .env gitignore, wrangler.jsonc custom domains. Lint/build green.


Bottom line

Conversion shelf + public SEO kitchen copy are addressed. Do not merge until product images are real listing photos for (nearly) all ASINs — 12/20 blank primaries is still a ship-stopper for a storefront.

VERDICT: REQUEST_CHANGES

Creators GetItems returns AssociateNotEligible. Drop unreliable
P/{ASIN} CDN placeholders (blank GIF 200s) so storefront uses quiet
monogram fallbacks. Clean remaining room/bamboo UI copy.

Co-authored-by: Dennis Simonson <DennisSimonson@users.noreply.github.com>
@SteveSimonson

Copy link
Copy Markdown
Owner Author

Third re-review (a95b175)

Checks: npm run lint ✅ · npm run build

Confirmed fixed from prior rounds

Item Status
Limited-time shelf OK — 10 products with limitedTime: true + ranks/expiry
Kitchen SEO shell OK — shop/why beauty copy; OG/preload → /brand/social.png
Shop/Product chrome OK — “All categories”, “beauty edit” (no bamboo/rooms on primary UI)
Shared wrong I/ photos Cleared — catalog images: [] for all 20 (no bad shared listing URLs)
Affiliate / secrets / lint-build Still clean

Remaining true blocker — monogram path is not what cards actually render

Emptying images: [] was the right catalog intent, but primaryDisplayImage / resolveProductImages still injects ASIN P/{ASIN} candidates for every product with an ASIN (src/lib/productImages.ts ~183–185) before the quiet monogram:

if (product.asin) {
  for (const c of amazonImageCandidates(product.asin, size)) push(c)
}
push(quietPlaceholderUrl(product))

Live CDN still returns HTTP 200 image/gif 43-byte 1×1 placeholders for ~12/20 ASINs (e.g. La Roche-Posay, Rare Beauty, Supergoop, Gisou…). A valid 1×1 GIF does not fire onError, so ProductCard never advances to the monogram.

Net effect of this commit for those ASINs: blank product wells, not monograms.

Minimal fix (pick one):

  1. Prefer monogram when catalog has no reliable /images/I/ URL — e.g. only call amazonImageCandidates if you opt in, or skip P/ candidates entirely until Creators is eligible; or
  2. In resolveProductImages, if product.images has no isReliableAmazonImage, push monogram only (no amazonImageCandidates).

After that, monogram-only MVP is an acceptable interim until AssociateNotEligible clears.

Known follow-ups (OK after the monogram path works — not merge blockers once images render correctly)

  • Quiz/vibes still kitchen-persona DNA (“Hosting board”, craft kitchen copy); quizSeo still “shop rooms that fit”
  • Restore Creators/AssociateNotEligible note in GROK-HANDOFF.md (confirmed in commit message, not in handoff body)
  • Real I/ listing photos via Creators/GetItems or verified scrape when eligible
  • Quiz rate-limit / EMAIL wrangler binding

Bottom line

Almost there — limited shelf + SEO/chrome are good. One more code path fix so empty catalog images actually yield monograms instead of silent blank GIFs, then this is shippable as a monogram interim MVP.

VERDICT: REQUEST_CHANGES

Amazon P/{ASIN} URLs often return 1×1 GIF with HTTP 200, so onError never
fires and product cards appear empty. Resolve images as reliable I/ CDN
URLs only, otherwise quiet monogram until Creators API is eligible.

Co-authored-by: Dennis Simonson <DennisSimonson@users.noreply.github.com>
@SteveSimonson

Copy link
Copy Markdown
Owner Author

Fourth re-review (58809eb)

Checks: npm run lint ✅ · npm run build

Blank-tile blocker — fixed

resolveProductImages no longer injects amazonImageCandidates / P/{ASIN} URLs into the display chain. With catalog images: [] (20/20):

  • primary image = quiet monogram (data:image/svg+xml…)
  • no HTTP-200 1×1 GIF path on cards
  • amazonImageCandidates remains defined for importer/tooling only (unused by card resolution)

Comment in productImages.ts documents the Creators-eligibility interim correctly.

Prior ship items (still good)

Item Status
Limited shelf 10× limitedTime: true with ranks/expiry
Kitchen SEO shell Beauty language on shop/why; social.png preload
Shop chrome “All categories”; beauty edit labels
Affiliate tags Still wired via amazon.ts
Secrets .env gitignored; no Creators secrets in tree
Lint / build Clean

Nits / follow-ups (non-blocking)

  1. Monogram-only merchandising is acceptable for MVP while AssociateNotEligible; when Creators works, re-fill real /images/I/ URLs and optionally re-enable safe candidates only after verification.
  2. Quiz/vibes still carry kitchen-house DNA (persona slots like “Hosting board”, craft kitchen prose; quizSeo still says “shop rooms that fit”). Secondary UX — fine as a fast follow-up.
  3. Handoff: re-add Creators/AssociateNotEligible status + “what to test after eligibility” so the next importer run isn’t tribal knowledge.
  4. Cosmetic: empty if (!hasReliableAmazon) { /* monogram only */ } block is a no-op — could drop the branch and keep the comment.
  5. Quiz rate-limit / EMAIL wrangler binding still deferred.

Verdict

Blank-tile P0 is gone. Limited shelf + beauty SEO shell + monogram-safe cards make this shippable as a public MVP with known follow-ups (real images post-Creators, vibe rewrite).

VERDICT: APPROVE_WITH_NITS

@SteveSimonson
SteveSimonson merged commit 105c53f into main Jul 28, 2026
1 check passed
@SteveSimonson
SteveSimonson deleted the feature/adazo-mvp-storefront branch July 28, 2026 20:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MVP: Adazo storefront on Cloudflare (adazo.com)

1 participant