[object Object]

← back to Designer Wallcoverings

Correct item-3 collection-image diagnosis: stale Boost fallback + orphaned home cards (not Boost-admin); add tested CSS fix + gated live-push

12841c9107cebf7f5afe0d7a8e6c6e1a6180839b · 2026-06-23 13:45:21 -0700 · Steve Abrams

Files touched

Diff

commit 12841c9107cebf7f5afe0d7a8e6c6e1a6180839b
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Tue Jun 23 13:45:21 2026 -0700

    Correct item-3 collection-image diagnosis: stale Boost fallback + orphaned home cards (not Boost-admin); add tested CSS fix + gated live-push
---
 .../collection-grid-toolbar-and-image-perf.md      | 161 ++++++++++++++++++---
 1 file changed, 138 insertions(+), 23 deletions(-)

diff --git a/pending-approval/collection-grid-toolbar-and-image-perf.md b/pending-approval/collection-grid-toolbar-and-image-perf.md
index 13137e5b..46b49ccc 100644
--- a/pending-approval/collection-grid-toolbar-and-image-perf.md
+++ b/pending-approval/collection-grid-toolbar-and-image-perf.md
@@ -48,34 +48,149 @@ consolidated theme to LIVE is the gated action below.
 
 ---
 
-## ITEM 3 — Oversized collection-grid images: root cause is the BOOST app, not theme Liquid
-
-The visible grid on `/collections/...` is rendered by the **Boost AI Search & Filter app**
-(`templates/collection.json` → app block `boost-ai-search-filter/product-filter`; wrapper
-`.boost-sd__product-filter-fallback`). The product images are fetched client-side by Boost and
-sized by **Boost's product-item template / image-size setting in the Boost app admin** — NOT by
-theme Liquid the theme token can edit. The live CSS only does `.boost-sd__product-item img{width:100%;
-height:auto}` (scales display, does not constrain SOURCE resolution → that's the "huge full-res"
-symptom). No `loading="lazy"` on the Boost imgs.
-
-**The theme's OWN grid is already correct:** the fallback `snippets/product-list-item.liquid` uses
-`{% render 'rimg', size:'600x600', lazy:true %}` and `snippets/rimg.liquid` emits proper sized URLs +
-`srcset` + lazy. So the theme isn't the offender.
-
-**Fix (Steve, in Boost SD admin — outside theme code):**
-- Boost SD → Display/Layout → Product image → set a sane max width (e.g. 400–600px, with retina
-  variant) instead of master/full-res; enable lazy-load if Boost exposes it.
-- This is an app-config change behind Steve's Boost admin login — surfaced, not auto-done.
-*(If you'd rather force it in theme CSS as a stopgap, I can add `loading="lazy"` via a Boost
-template hook only if Boost's theme-app-extension exposes the product-item snippet — it does not in
-the current setup, so the admin setting is the right lever.)*
+## ITEM 3 — Oversized collection-grid images — CORRECTED DIAGNOSIS (supersedes the Boost-admin theory below)
+
+> **⚠️ The earlier "it's the Boost image-size admin setting" conclusion was WRONG.** Re-measured
+> in-browser at desktop 1440px AND mobile 390px on BOTH the live theme (142250278963) and the dev
+> theme (143947038771). The **Boost HYDRATED grid renders CORRECTLY** (`.boost-sd__product-item`:
+> 8 cards @ ~403px desktop / ~57px mobile, images at `width=700`). **The Boost image-size setting
+> does NOT need changing.** The struck-through text below is retained only as a record of the
+> superseded theory.
+
+### What is actually oversized (measured)
+The "huge images" are **theme-native `.product-list-item` cards rendering full-width (1240–1440px)**
+in two distinct places, neither of which is the live Boost grid:
+
+1. **Stale Boost server-rendered FALLBACK (collection page).** `.boost-sd__product-filter-fallback`
+   is Boost's pre-hydration server markup, meant to be hidden once Boost hydrates. On live it is
+   **never hidden** — its theme `section.collection` + loose `article.product-list-item` cards stack
+   full-width below the real grid (measured fallback height ~7,768px of giant cards; collection
+   `pageH` 14,308px). **TRAP:** the GOOD hydrated grid (`.boost-sd-container` / `.boost-sd__product-item`)
+   is *nested inside the same `.boost-sd__product-filter-fallback` container*, so a naive
+   `display:none` on the fallback zeros the good grid too. The fix must hide the **stale theme branch
+   only** (`section.collection` + loose cards), never `.boost-sd-container`.
+
+2. **Orphaned featured-collection cards (homepage).** Home `.product-list-item` cards that the
+   theme's `grid.js` was supposed to lay into `.home-products-content` are left **orphaned attached
+   directly to `.main-content` / `<body>`** (DOM-probed: cards #4/#7 are direct children of `<body>`),
+   rendering at full 1440px. This is a downstream symptom of the **grid.js init-abort** documented in
+   the companion memo `grid-js-init-abort-and-dev-build.md` (a section ctor throws → `_initSections`
+   aborts → the featured-collection carousel never lays the cards out).
+
+(The theme's `snippets/product-list-item.liquid` / `rimg.liquid` ARE correct — `size:'600x600'`,
+`srcset`, lazy. The cards are blown out because they're rendered **outside any grid container**, not
+because the image source is wrong.)
+
+### The STAGED fix (dev theme 143947038771, reversible, dev-only — NOT live)
+A single CSS block appended to `assets/custom.css` (which `layout/theme.liquid` links on every page),
+marked `/* >>> dw-collection-grid-fix START >>> */ … END`, removable in one pass. Source of truth:
+`shopify/grid-js-fix/dw-collection-grid-fix.css`. Backup of the pre-edit dev asset:
+`shopify/grid-js-fix/backups/custom.css.dev-143947038771.before`.
+
+What it does:
+- **(A) Collection:** scoped to `body.boost-sd__search-widget-init-enabled` (Boost's post-hydration
+  body class), hides the stale theme fallback (`.boost-sd__product-filter-fallback > section.collection`,
+  loose `article.product-list-item`, and `.shopify-section:not(:has(.boost-sd-container))`) while
+  explicitly keeping `.boost-sd-container article.product-list-item` visible. Pre-hydration the
+  fallback still shows (no flash of empty grid).
+- **(B) Homepage:** forces `section.home-products` into a responsive CSS grid and clamps every
+  `.product-list-item` (and any card orphaned onto `body`/`.main-content`) to `max-width:360px` so a
+  card can **never** render full-bleed — even if `grid.js` init still partially fails. This is the
+  DTD-approved (3/3, 2026-06-23) defensive net; the `grid.js` init-abort fix in the companion memo
+  remains the primary mechanism.
+
+### Measured before → after (TESTED — staged CSS applied to the real served DOM, both viewports)
+| Page / viewport | BLOWN `.product-list-item` (>500px) BEFORE | AFTER | Boost hydrated grid AFTER |
+|---|---|---|---|
+| Home @1440 | 5 (max 1440px) | **0** (7 cards visible, ≤360px) | n/a |
+| Collection @1440 | 7 (max 1440px) | **0** (stale hidden) | **intact: 8 @403px** |
+| Home @390 | 0 | **0** (7 visible, ≤360px) | n/a |
+| Collection @390 | 0 | **0** (stale hidden) | **intact: 8 @57px** |
+
+Collection `pageH` after fix: 14,308px → **2,754px** (the stacked giant cards are gone). Homepage
+`pageH`: 10,063px → 3,896px.
+
+**Honest scope of proof:** CSS application is deterministic — the measurements above are the *real
+collection/home page DOM* with this exact CSS applied. The staged CSS is confirmed present on dev
+theme 143947038771's `custom.css` via the Admin API (marker found, 41,241 bytes). The one thing I
+could NOT do headless: load the dev theme through Shopify's `?preview_theme_id=` URL — anonymous
+(non-admin) requests are served the LIVE theme's assets, not the dev theme's (`devCssServed=false`
+in the served-preview probe). So the final pixel-perfect confirm on the *served dev theme* is the
+authenticated **Preview** button, which only Steve can open.
+
+### Steve — verify on dev, then approve the live push
+**Verify (authenticated):** Shopify admin → Online Store → Themes → "★ 5.0 Grid+Infinite FIX"
+(143947038771) → **Preview** → open the homepage and
+`/collections/acoustical?pf_t_product_type=Wallcovering&pf_t_color=Green`. Paste in console:
+```js
+({ blown: [...document.querySelectorAll('.product-list-item img')].filter(i=>i.getBoundingClientRect().width>500).length,
+   boost: document.querySelectorAll('.boost-sd__product-item').length })
+// WANT: blown === 0, boost === 8 (collection) ; on home blown === 0 with cards still visible
+```
+
+**Live-push commands I will run on your go** (theme token via `/secrets` `SHOPIFY_THEME_TOKEN`,
+never hardcoded; appends the SAME marked block to LIVE 142250278963's `custom.css`, idempotent,
+backs up first):
+```bash
+TOKEN=$(grep -m1 '^SHOPIFY_THEME_TOKEN=' ~/Projects/secrets-manager/.env | cut -d= -f2- | tr -d '"')
+LIVE=142250278963
+cd ~/Projects/Designer-Wallcoverings
+# 1) backup live custom.css
+python3 - "$TOKEN" "$LIVE" <<'PY'
+import sys,json,urllib.request,urllib.parse
+tok,t=sys.argv[1],sys.argv[2]
+q=urllib.parse.urlencode({'asset[key]':'assets/custom.css'})
+u=f"https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-10/themes/{t}/assets.json?{q}"
+v=json.load(urllib.request.urlopen(urllib.request.Request(u,headers={'X-Shopify-Access-Token':tok})))['asset']['value']
+open(f'shopify/grid-js-fix/backups/custom.css.live-{t}.before','w').write(v); print('backed up',len(v),'bytes')
+PY
+# 2) append the marked fix block (idempotent) and PUT to live
+python3 - "$TOKEN" "$LIVE" <<'PY'
+import sys,re,json,urllib.request,urllib.parse
+tok,t=sys.argv[1],sys.argv[2]
+q=urllib.parse.urlencode({'asset[key]':'assets/custom.css'})
+base=json.load(urllib.request.urlopen(urllib.request.Request(
+  f"https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-10/themes/{t}/assets.json?{q}",
+  headers={'X-Shopify-Access-Token':tok})))['asset']['value']
+fix=open('shopify/grid-js-fix/dw-collection-grid-fix.css').read()
+S='/* >>> dw-collection-grid-fix START >>> */'; E='/* <<< dw-collection-grid-fix END <<< */'
+base=re.sub(re.escape(S)+r'.*?'+re.escape(E),'',base,flags=re.S).rstrip()+'\n'
+out=base+'\n'+S+'\n'+fix+'\n'+E+'\n'
+body=json.dumps({'asset':{'key':'assets/custom.css','value':out}}).encode()
+r=urllib.request.urlopen(urllib.request.Request(
+  f"https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-10/themes/{t}/assets.json",
+  data=body,method='PUT',headers={'X-Shopify-Access-Token':tok,'Content-Type':'application/json'}))
+print('PUT live custom.css OK ->', json.load(r)['asset']['size'],'bytes')
+PY
+# 3) re-verify the live URLs (node verify-final-css-fix.js style, no injection)
+```
+*Rollback:* re-PUT `shopify/grid-js-fix/backups/custom.css.live-142250278963.before`, or strip the
+marked block.
+
+---
+
+<details><summary>SUPERSEDED theory (kept for the record — do NOT act on this)</summary>
+
+~~The visible grid on `/collections/...` is rendered by the Boost AI Search & Filter app … sized by
+Boost's product-item image-size setting in the Boost app admin … Fix (Steve, in Boost SD admin): set
+a sane max width.~~ — **Wrong.** The Boost hydrated grid renders correctly; the oversized cards are
+the stale theme fallback + orphaned home cards (see corrected diagnosis above). No Boost-admin change
+is needed.
+</details>
 
 ---
 
 ## Steve, paste to proceed
 - [ ] OK to run dev-theme consolidation steps 1–4 on 143947038771 (dev writes only, fixes the line-85 regression)
 - [ ] After dev is clean + you review the preview, approve PUBLISH of the consolidated theme to LIVE (infinite-scroll goes live then)
-- [ ] Set the Boost SD product-image max width (item 3) in the Boost admin
+- [ ] **ITEM 3 (CORRECTED):** I verified the dev Preview (blown===0, Boost grid intact) → **approve the
+      live-push of the `dw-collection-grid-fix` CSS block to LIVE 142250278963's `custom.css`** (commands above).
+- [ ] ~~Set the Boost SD product-image max width in the Boost admin~~ — **NOT NEEDED** (superseded; the Boost grid is fine).
 - [ ] (Optional) retire the redundant second desktop density slider (`dw-grid-control.js`)
 
-**$ cost:** $0 (local + read-only theme API + read-only public page). No metered API.
+**Note:** This item-3 CSS fix is complementary to the `grid.js` init-abort fix in
+`grid-js-init-abort-and-dev-build.md` — the CSS net is the belt, the grid.js fix is the suspenders.
+Both are staged on dev 143947038771; do both.
+
+**$ cost:** $0 (local Playwright + read-only public pages + read/write theme API to the UNPUBLISHED
+dev theme only). One DTD panel: local Qwen (free) + Codex ~**$0.0035**. Total ≈ **$0.004**.

← b6165db6 Stage collection/home oversized-images CSS fix on dev theme  ·  back to Designer Wallcoverings  ·  auto-save: 2026-06-23T13:52:03 (9 files) — shopify/audit/col 25b799da →