chore: pair handoff docs + ship readiness - #2
Conversation
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>
Adversarial review — PR #2 + full MVP on
|
| 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.tsalways setstag=on product + search URLs;ProductCard/ PDP buy CTAs go throughaffiliateUrlwithrel="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_TAGat build time (Vite inlines it). Deploying without.envsilently ships the fallback — OK only while that is the real Store ID. scripts/bsr/fill-quota.mjshardcodesassociateTag: 'iu0e3-20'in the snapshot writer instead of reading env (drift risk).
- Production must set
- Creators credentials stay non-
VITE_*in.env.example— good. .envis 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: workeradazo, custom domainsadazo.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: trueitems. - Home primary CTA →
/shop?limited=1→ 0 products (“No matches” / “0 options in this drop”). - Worker/route-meta still indexes
/shop?limited=1and 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.tsshopSeo: 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,hostslots = “Hosting board”, “Tabletop moment”,patiooutdoor 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.jsonlook 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
AssociateNotEligibleblock — 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
tagfound 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.)
.gitignorecovers.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
- 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.
- 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. - Fix per-product Amazon images (no shared wrong
I/URLs). - Add real brand assets for hero + social/why preloads (or stop referencing missing paths).
- Restore Creators/eligibility status in handoff (or
docs/) until GetItems works. - (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
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>
Re-review after REQUEST_CHANGES fixesCommits reviewed: Previous P0 status
Remaining blocker: catalog imagesImages were switched from shared That pattern is explicitly treated as unreliable in
Blank GIFs (broken primary image): Working JPEGs: CeraVe, Neutrogena, The Ordinary, Olaplex, REVLON, LANEIGE, Vital Proteins, Tatcha. Required fix: restore per-product Nits (non-blocking for this PR if images fixed)
Affiliate / secrets / domainsUnchanged and still OK: tag wiring, Bottom lineConversion 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>
Third re-review (
|
| 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):
- Prefer monogram when catalog has no reliable
/images/I/URL — e.g. only callamazonImageCandidatesif you opt in, or skipP/candidates entirely until Creators is eligible; or - In
resolveProductImages, ifproduct.imageshas noisReliableAmazonImage, push monogram only (noamazonImageCandidates).
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);
quizSeostill “shop rooms that fit” - Restore Creators/
AssociateNotEligiblenote inGROK-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>
Fourth re-review (
|
| 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)
- 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. - Quiz/vibes still carry kitchen-house DNA (persona slots like “Hosting board”, craft kitchen prose;
quizSeostill says “shop rooms that fit”). Secondary UX — fine as a fast follow-up. - Handoff: re-add Creators/
AssociateNotEligiblestatus + “what to test after eligibility” so the next importer run isn’t tribal knowledge. - Cosmetic: empty
if (!hasReliableAmazon) { /* monogram only */ }block is a no-op — could drop the branch and keep the comment. - 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
Fixes #1
Summary
main(beauty catalog, Worker SEO, Associates wiring)Pair
@DennisSimonson @SteveSimonson
Risk
Low — docs + string cleanup only
Test plan
npm run lintnpm run build