← back to Designer Wallcoverings
pending-approval/done/grid-js-init-abort-and-dev-build.DONE.md
140 lines
# grid.js init-abort + shipped DEV build — root cause, staged fix, gated live push
**Owner:** vp-dw-commerce · **Drafted:** 2026-06-23 · **Status:** root-caused; fix STAGED on dev theme; LIVE push + final visual confirm AWAITING STEVE
**Gate reason:** live customer-facing theme-asset writes (grid.js + 2 Liquid files) on the published theme.
**Live theme (verified, role==main):** **142250278963 "Steves Version 5.0"** (Out of the Sandbox "Grid" v7.1.0).
**Dev theme used for staging:** **143947038771 "★ 5.0 Grid+Infinite FIX (approve)"** (same theme the parallel `collection-grid-toolbar-and-image-perf.md` memo named as the consolidation base).
> **Read this WITH `pending-approval/collection-grid-toolbar-and-image-perf.md`.** That memo
> correctly attributes the *Boost-app* collection grid's oversized images to the Boost SD admin
> image-size setting. THIS memo covers a **separate, deeper defect** that the Boost finding does
> NOT explain: the theme's own `grid.js` JavaScript bundle **crashes on init and aborts before any
> theme-managed grid/carousel lays out** — which is why the homepage featured-collection carousels
> and the OOTS-native (non-Boost) product cards render full-width/native-size. Both fixes are
> needed; they don't conflict.
---
## 1. Confirmed root cause (live-DOM forensics + reading the readable production bundle)
The theme's `grid.js` registers all section behaviors through a `ShopifySectionsManager`. On the
live markup, **two section constructors throw because DW's custom Liquid removed DOM hooks the
Out-of-the-Sandbox section classes dereference with NO null-guard.** The throw propagates out of
`ShopifySectionsManager._initSections`, which **aborts the whole init loop — so NO section after the
throw initializes**, including the product-grid carousels/masonry. Result: `window.Flickity`
undefined, `.flickity-enabled` = 0, and theme-managed grids fall back to `display:block`, sizing
cards to the image's intrinsic width = the "giant blown-out images."
**Throw #1 — `StaticHeader._setSearchWidth` (header):**
```
TypeError: Cannot read properties of null (reading 'style')
at StaticHeader._setSearchWidth (grid.js) // this.headerSearch.style.width = ...
at new StaticHeader → ShopifySectionsManager._createInstance → _initSections
```
The OOTS `StaticHeader` queries `[data-header-search]`, `[data-header-search-button]`,
`[data-header-search-button-close]`. DW's custom header (`.header-search-inline` + `.search-takeover`
+ `data-header-search-toggle`) **replaced the original search form and removed all three hooks**
(verified: 0 of each in live `sections/header.liquid` and `snippets/search-form.liquid`).
`this.headerSearch` is null → constructor throws → manager aborts.
**Throw #2 — `ProductListItem` constructor (collection cards):**
```
TypeError: Cannot read properties of null (reading 'dataset')
at new ProductListItem (grid.js) // this.el.closest('[data-product-hover]').dataset.productHover
at new StaticCollection → _initSections
```
The per-card `[data-product-hover]` wrapper was dropped from `snippets/product-list-item.liquid`
(only the section-level one remained: live DOM showed `[data-product-hover]` = 1 vs 8 cards).
`.closest(...)` returns null → `.dataset` throws.
**Independent defect (asset hygiene): the live `grid.js` is a webpack `eval-source-map` DEV build.**
2,022,084 bytes, 89 `eval()` calls, opens with the webpack "ATTENTION: …neither made for production…"
banner. The correct production build is 554,793 bytes, 0 evals, readable stack traces. The dev build
has propagated to every theme touched since ~2026-02-12. **Both builds crash identically on the
broken markup** — so the dev-build is NOT the cause of the init crash, but it is ~3.6× the bytes,
un-debuggable in prod, and not a production artifact. (The readable production build is exactly what
let me capture the stack traces above.)
## 2. Where the good production grid.js came from
Last-known-good production `grid.js` recovered from an **older unpublished theme version still in the
store: `141318651955` "Variant discount issue fix | 2/6/26" (2026-02-05)** — the only theme of 15 not
yet poisoned by the dev build. Pulled via the Admin asset API, validated: `node --check` passes, 0
evals, self-inits via the webpack bootstrap IIFE, SAME entry module `./source/scripts/grid.js` as the
current build, contains Flickity + Masonry + the `flickity-enabled` class. Saved at
`shopify/grid-js-fix/grid.js.production-554k.from-theme-141318651955`.
*(DTD panel 3/3 chose "restore last-known-good prod build" over "rebuild webpack from the eval modules.")*
## 3. What is STAGED on dev theme 143947038771 (reversible; no live change)
| Asset | Change | Backup |
|---|---|---|
| `assets/grid.js` | dev eval-source-map build → 554KB production build | `shopify/grid-js-fix/backups/grid.js.dev-143947038771.before` |
| `snippets/product-list-item.liquid` | added `data-product-hover="{{ product_hover }}"` to the `<article>` | `…/backups/product-list-item.liquid.live-142250278963.before` |
| `sections/header.liquid` | added a visually-hidden, inert `.header-search` shim carrying `[data-header-search]` + `[data-header-search-button]` + `[-close]` (display:none, off-screen, `tabindex=-1`, `aria-hidden`) so `StaticHeader` constructs without throwing — ZERO visible UX change | `…/backups/header.liquid.live-142250278963.before` |
Patched copies live at `shopify/grid-js-fix/patched/`. The staged dev grid.js verified server-side:
0 evals, 554,793 bytes, `flickity-enabled` string present.
## 4. What is PROVEN vs what Steve must confirm (honest scope)
**PROVEN (offline + asset API):**
- The exact throw sites + null elements (stack traces + live-DOM hook counts).
- After the patches, the init-aborting `StaticHeader`/`ProductListItem`/`_initSections` throws are
GONE (no longer raised), and per-card `data-product-hover` + the header hooks are present.
- Collection cards that ARE inside `.collection-products[data-collection-grid]` render correctly
(CSS grid, ~77–103px). The blown-up cards are the ones in the bare `section.collection > div`
(`display:block`) that the theme-managed grid never laid out.
- The 554KB production build is valid, self-initing, same source/entry as live.
**NOT yet visually confirmed (requires the authenticated admin "Preview"):** that Flickity/Masonry
then actually engages and the homepage carousels + the non-Boost cards render constrained. An
offline route-swap CANNOT fully reproduce the Shopify theme runtime (Boost SD app, section JSON,
Flickity CSS/lifecycle), so I am **not** claiming the visual fix as verified. This is the one step
only Steve can do cleanly (the preview session comes from the admin Preview button).
## 5. Steve — verify on dev, THEN approve the live push
**Step A — open the dev preview (authenticated):** Shopify admin → Online Store → Themes →
"★ 5.0 Grid+Infinite FIX (approve)" (143947038771) → **Preview**. Open the homepage and a collection,
e.g. `/collections/acoustical?pf_t_product_type=Wallcovering&pf_t_color=Green`.
**Step B — paste this in the browser console on the preview to confirm init:**
```js
console.log({
Flickity: typeof window.Flickity,
flickityEnabled: document.querySelectorAll('.flickity-enabled').length,
blownCards: [...document.querySelectorAll('.product-list-item img')]
.filter(i => i.getBoundingClientRect().width > 700).length
});
// WANT: Flickity !== 'undefined' (on home), flickityEnabled > 0, blownCards === 0
```
If `blownCards === 0` and the homepage carousels render as carousels, the fix is good.
**Step C — if it looks right, paste to approve the LIVE push.** I will then apply the SAME three
assets to live theme **142250278963** (backups already captured), 90s apart, and re-verify on the
live URL. Exact commands I will run (theme token via `/secrets` `SHOPIFY_THEME_TOKEN`, never hardcoded):
```bash
TOKEN=$(grep '^SHOPIFY_THEME_TOKEN=' ~/Projects/secrets-manager/.env | cut -d= -f2)
LIVE=142250278963
# 1) grid.js (production build)
curl -s -X PUT "https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-10/themes/$LIVE/assets.json" \
-H "X-Shopify-Access-Token: $TOKEN" -H 'Content-Type: application/json' \
--data-binary @<(python3 -c "import json;print(json.dumps({'asset':{'key':'assets/grid.js','value':open('$HOME/Projects/Designer-Wallcoverings/shopify/grid-js-fix/grid.js.production-554k.from-theme-141318651955').read()}}))")
# 2) snippets/product-list-item.liquid 3) sections/header.liquid (same pattern, from shopify/grid-js-fix/patched/)
```
## 6. Watch-item (not blocking this fix)
- The **homepage featured-collection sections currently contain only ONE product each**; with the
carousel restored a 1-item section should still size correctly, but confirm the "BRAND MCKENZIE UK"
section specifically in Step A. If a single-item section still looks off after the fix, that is a
CSS/section-config follow-up, separate from this init-abort fix.
- This fix is **complementary to** the Boost SD image-size admin setting in
`collection-grid-toolbar-and-image-perf.md` item 3 — do both.
## Steve, paste to proceed
- [ ] I confirmed the dev preview (Step A/B): Flickity engages + no blown cards → **approve LIVE push of all 3 assets to 142250278963**
- [ ] OR: dev preview still shows blown cards → keep digging (I'll escalate to rebuilding the bundle / the single-item CSS path)
**$ cost:** $0 (local Playwright + read-only public pages + read/write theme API to the UNPUBLISHED dev theme only; the 2 DTD panels used local Qwen + ~$0.02–0.05 Codex each ≈ **$0.04–0.10 total**).