← back to Designer Wallcoverings
auto-save: 2026-06-29T15:24:16 (3 files) — pending-approval/boost-filter-consolidation-2026-06-25 vendor-scrapers/china-seas-refresh onboarding/
80f9541f122ba67bbd80a4244f90e89af8546f9d · 2026-06-29 15:24:21 -0700 · Steve Abrams
Files touched
A onboarding/sangetsu-lilycolor/DOSSIER.mdA onboarding/sangetsu-lilycolor/lily-feed-recon.cjs
Diff
commit 80f9541f122ba67bbd80a4244f90e89af8546f9d
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Mon Jun 29 15:24:21 2026 -0700
auto-save: 2026-06-29T15:24:16 (3 files) — pending-approval/boost-filter-consolidation-2026-06-25 vendor-scrapers/china-seas-refresh onboarding/
---
onboarding/sangetsu-lilycolor/DOSSIER.md | 89 +++++++++++++++++++++++
onboarding/sangetsu-lilycolor/lily-feed-recon.cjs | 54 ++++++++++++++
2 files changed, 143 insertions(+)
diff --git a/onboarding/sangetsu-lilycolor/DOSSIER.md b/onboarding/sangetsu-lilycolor/DOSSIER.md
new file mode 100644
index 00000000..d4f2606e
--- /dev/null
+++ b/onboarding/sangetsu-lilycolor/DOSSIER.md
@@ -0,0 +1,89 @@
+# Vendor Onboarding Dossier — Sangetsu (Goodrich) & Lilycolor
+
+**Status:** STAGED / recon complete — **nothing online, nothing pushed to Shopify.**
+**Authorized by:** Steve, 2026-06-29 ("Onboard but do not show online until approved. both companies and dig into catalogs too").
+**Gate:** Onboarding Activation Gate + publish gate fully in force. Publish only on Steve sign-off.
+
+---
+
+## 0. Disambiguation (the trap we avoided)
+
+The originating customer note said *"sangetsu and goodrich catalogs."* These are **not two vendors.**
+**Goodrich = Sangetsu's international/export brand** ("Sangetsu Goodrich", sangetsugoodrich.com,
+sangetsu-goodrich.co.th/.vn, goodrichglobal.com). Onboarding "Goodrich" as a separate vendor
+would have created a duplicate/garbage vendor that collides on every SKU.
+
+→ **Two vendors to onboard, not three:**
+1. **Sangetsu** (incl. the Goodrich export catalog)
+2. **Lilycolor** (リリカラ)
+
+Both confirmed ABSENT from the 108-vendor registry (`3-scraper-system-analysis.json`) and from
+`~/Projects` — clean adds, no vendor-level collision.
+
+---
+
+## 1. Lilycolor (リリカラ) — HIGH confidence, feed-first
+
+| Field | Finding |
+|---|---|
+| Founded | 1907, Tokyo. Wallpaper + curtains + flooring. |
+| Trade catalogs | WILL (LW####), LIGHT (LL6###), V-wall (LV2###/LV3###), BASE, Digital Deco. |
+| **Machine-readable feed** | ✅ **`https://shop.lilycolor.co.jp/products.json`** → 200 `application/json`, full Shopify schema. |
+| Feed size | ≥250 products/page (paginated `?limit=250&page=N`). Consumer paste-on (のり付き) shop = a SUBSET of the full trade line. |
+| SKU prefixes seen in feed | **LB, LV, LW** (variant.sku). Trade line adds LL6### etc. |
+| Sample-variant convention | Already present in feed: handle `…___sample`, title `…|サンプル`. Maps cleanly to our sample-variant rule. |
+| Language | **Japanese** titles + body_html → **translation pass required** for customer-facing copy. |
+| Specs in feed | width (有効巾, e.g. 92.5cm), composition (塩化ビニル = vinyl), fire grade (F☆☆☆☆, 準不燃=semi-noncombustible) embedded in body_html table. |
+| English resellers (cross-ref) | softhome.sg/wallcoverings/lilycolor (WILL/LIGHT/V-wall digital catalogs). |
+
+**Scraper strategy:** feed-first on `products.json` (paginate to exhaustion) for the consumer line,
+**plus** the trade `allpatterns` web-catalog pages (WILL/LIGHT/V-wall) for the full line. Translate
+JA→EN at enrichment. This is the *easy* one — the previous "scattered, low-confidence" read was wrong
+once the Shopify endpoint was found.
+
+**Proposed DW series prefix:** `DWLC` (proposal only — real assignment lives in `vendor_registry`, gated).
+
+---
+
+## 2. Sangetsu (incl. Goodrich) — MEDIUM confidence, DOM-rendered
+
+| Field | Finding |
+|---|---|
+| US/export face | `sangetsugoodrich.com/en/...` (home 200). `/wp-json/` → **403 (anti-bot)** → no open WP REST. |
+| Regional product pages | `sangetsu-goodrich.co.th`, `.vn`, `goodrichglobal.com/singapore` — per-SKU pages at `/products/wallpaper-wallcovering/<category>/<pattern>/`. |
+| `sitemap.xml` | 404 (no open sitemap at root). Need to discover via collection/category crawl or a rendered crawl. |
+| Catalog PDFs | `sangetsu.co.jp/english/pdfdownload/...` (TEXTURE & MATERIAL 2025-2029 XSELECT, etc.) — usable for spec backfill. |
+| Grasscloth / natural line (relevant to the customer ask) | Woven Grass (GSD1038-1041), Savannah (Y476xx, "matte and metallic"), Sass-a-Grass (Y474xx), Sanshin (AZ527xx, "metallic shimmer"), Virtuoso (AZ522xx, "soft shimmer / metallic glamour"), Harvest (HV21-xx), Ambience (LX199x, sisal). |
+| SKU schemes | Mixed: GSD####, Y#####, AZ#####, LX####, HV##-## (per collection). |
+| Specs | width 52"/54" Type II, 20oz, Osnaburg backing (commercial); residential lines differ. |
+
+**Scraper strategy:** **feed-first will NOT work** (wp-json blocked, no sitemap). Use a rendered
+crawl (Playwright / dev-browser) seeded from the category index pages, OR Browserbase if anti-bot
+bites. Spec backfill from the English PDFs. This is the harder vendor — onboard **Lilycolor first**,
+Sangetsu second.
+
+**Proposed DW series prefix:** `DWSG` (Sangetsu Goodrich) — proposal only, gated.
+
+---
+
+## 3. Standing gates that apply before ANY publish
+
+1. **Dedup** by series prefix + mfr_sku against **both** `dw_sku_registry` (~84k) AND `shopify_products` (~160k). (Requires a live psql session — not run from here.)
+2. **Full-page scrape** — all images + width + repeat + composition + weight + fire rating + all metafields, not just listing fields.
+3. **Settlement gate** — run on any tropical/foliage/botanical pattern before publish (both lines have naturals).
+4. **Activation Gate** — every SKU needs all 5: sample variant, product variant, complete pricing (no $0/null), description, ≥2 tags. **No confirmed vendor COST → SKU stays HELD/draft, never force-priced.** Neither vendor's net cost is known yet → this is the real blocker to activation.
+5. **Pricing** — non-Kravet formula cost/0.65/0.85 once cost is confirmed; sample = standard sample price.
+6. **Cadence-only creation** — only the metered 18/hr `cadence-import.js` may create products. No burst jobs.
+
+## 4. What is DONE (this session, all reversible/offline)
+- Disambiguated Goodrich→Sangetsu. Confirmed both absent from registry.
+- Confirmed Lilycolor Shopify feed (live pull proof: `lily-feed-recon.cjs`).
+- Characterized Sangetsu platform (DOM-rendered, anti-bot) + grasscloth line.
+- Added 2 registry entries (status `onboarding`, `integrated:false`) — see registry diff.
+- Disco/lookalike shortlist for the customer: `disco-candidates-for-andrew.md`.
+
+## 5. What is GATED (needs Steve sign-off — see pending-approval memo)
+- Building + integrating the two scrapers into `lib/scrapers/`.
+- Assigning real `vendor_registry` rows + DW prefixes.
+- Any cost confirmation / pricing.
+- Any Shopify create / publish (stays "Staged for New" → draft → active only on approval).
diff --git a/onboarding/sangetsu-lilycolor/lily-feed-recon.cjs b/onboarding/sangetsu-lilycolor/lily-feed-recon.cjs
new file mode 100644
index 00000000..b315a1b7
--- /dev/null
+++ b/onboarding/sangetsu-lilycolor/lily-feed-recon.cjs
@@ -0,0 +1,54 @@
+#!/usr/bin/env node
+/**
+ * Lilycolor feed-first recon — READ-ONLY.
+ * Pulls the live Shopify products.json feed and reports counts, SKU prefixes,
+ * and grasscloth/cane candidates. Does NOT write anywhere, does NOT touch Shopify/dw_unified.
+ *
+ * Usage: node lily-feed-recon.cjs [maxPages]
+ */
+const https = require('https');
+
+const BASE = 'https://shop.lilycolor.co.jp/products.json';
+const maxPages = parseInt(process.argv[2] || '6', 10);
+
+function get(url) {
+ return new Promise((resolve, reject) => {
+ https.get(url, { headers: { 'User-Agent': 'Mozilla/5.0 (DW-recon)' } }, (res) => {
+ let body = '';
+ res.on('data', (c) => (body += c));
+ res.on('end', () => {
+ try { resolve(JSON.parse(body)); } catch (e) { reject(e); }
+ });
+ }).on('error', reject);
+ });
+}
+
+(async () => {
+ const all = [];
+ for (let page = 1; page <= maxPages; page++) {
+ const d = await get(`${BASE}?limit=250&page=${page}`);
+ const ps = (d && d.products) || [];
+ if (!ps.length) break;
+ all.push(...ps);
+ process.stderr.write(`page ${page}: +${ps.length} (total ${all.length})\n`);
+ }
+
+ const prefixes = {};
+ const naturals = [];
+ for (const p of all) {
+ for (const v of p.variants || []) {
+ const m = String(v.sku || '').match(/^([A-Za-z]+)/);
+ if (m) prefixes[m[1].toUpperCase()] = (prefixes[m[1].toUpperCase()] || 0) + 1;
+ }
+ if (/グラスクロス|麻|籐|cane|grass|和紙|織物/i.test(p.title)) {
+ naturals.push({ title: p.title, handle: p.handle });
+ }
+ }
+
+ console.log(JSON.stringify({
+ totalProducts: all.length,
+ pagesPulled: Math.min(maxPages, Math.ceil(all.length / 250)),
+ variantSkuPrefixes: prefixes,
+ naturalTextureCandidates: naturals.slice(0, 40),
+ }, null, 2));
+})().catch((e) => { console.error('FAILED:', e.message); process.exit(1); });
← fdeaccb1 auto-save: 2026-06-29T14:53:15 (5 files) — pending-approval/
·
back to Designer Wallcoverings
·
Onboard (staged/offline) Sangetsu + Lilycolor: registry entr 6171cced →