{"slug":"dw-collections-viewer","total":22,"limit":100,"offset":0,"since":null,"commits":[{"hash":"48ca48c","date":"2026-07-13 14:38:36 -0700","author":"Steve","subject":"chore: v0.2.0 — similar-pattern search feature (session close)","body":""},{"hash":"1d1ab8c","date":"2026-07-13 12:20:52 -0700","author":"Steve Abrams","subject":"similar-pattern search: per-tile ≈ button → /api/similar proxy to all.dw (creds server-side) → scored live substitutes in a shared panel below the product slider","body":""},{"hash":"aa7d928","date":"2026-06-10 09:22:32 -0700","author":"SteveStudio2","subject":"snapshot before dep reinstall + pm2 restart","body":""},{"hash":"61f62d9","date":"2026-05-18 20:24:19 -0700","author":"SteveStudio2","subject":"Add rel=noopener noreferrer to Open site external link","body":""},{"hash":"cd8ae33","date":"2026-05-13 08:57:52 -0700","author":"Steve","subject":"snapshot: 3 file(s) changed, +2 new, ~1 modified","body":""},{"hash":"deda82f","date":"2026-05-07 08:59:43 -0700","author":"Steve","subject":"dw-collections-viewer: gold ↕<sort> pill on tiles when persisted sort != default 'textures'; surfaces last_sort_applied at a glance","body":""},{"hash":"cbb7a20","date":"2026-05-06 20:58:49 -0700","author":"Steve","subject":"dw-collections-viewer: 'Preview sort' button — re-render with chosen sort but skip deploy/pm2-restart so user can eyeball the order before pushing live","body":""},{"hash":"15a2c8f","date":"2026-05-06 20:24:39 -0700","author":"Steve","subject":"dw-collections-viewer: stale-products pill (>30 days mtime) on each tile + 'Stale' bulk-select option; surfaces last_render_iso/age_days/is_stale via /api/sites","body":""},{"hash":"f3e88a0","date":"2026-05-06 19:47:36 -0700","author":"SteveStudio2","subject":"Fix HTML tokenizer breaking outer script — escape nested </script> in template literal","body":"renderDetail() injects a giant template-literal HTML block via\ninnerHTML; that block contains a nested <script>(restore deploy-sort)</script>\nhelper. Browsers' HTML tokenizer doesn't respect JS template literals — when\nit hits the inner </script>, it terminates the OUTER <script> block too.\nEverything after that closing tag (including the outer template's closing\nbacktick) became raw HTML, leaving the main JS body unterminated:\n'Unexpected end of input'. Page rendered shell only, no site cards.\n\nFix: split the open tag as <` + `script> and escape the close as <\\/script>\ninside the template literal. Tokenizer no longer sees a script boundary.\n\nVerified via debate-team-fast (Claude + Kimi + Qwen3 all 3/3): correct fix.\nFuture refactor (ticket): move the inline restore script OUT of the template\nliteral entirely (data-attribute + DOMContentLoaded hook). Add a pre-commit\ngrep for unescaped </script> inside backtick template literals."},{"hash":"a0cea68","date":"2026-05-06 19:20:23 -0700","author":"Steve","subject":"save+deploy: persist chosen sort to per-site rules; UI pre-populates from server-side rules.sort with localStorage fallback","body":""},{"hash":"dd68026","date":"2026-05-06 17:56:42 -0700","author":"SteveStudio2","subject":"Hero resolution probe + HD/MED/SD badges + upscale to largest variant","body":"Steve flagged: many hero images look blurry full-page because the source is\na small Shopify variant (e.g. 480x480). Two fixes:\n\n1. largestShopifyImage(url) — strips _NxN size suffix from any\n   cdn.shopify.com / designerwallcoverings.com URL so the master is fetched\n   for both card thumbnails AND drag-drop hero pins.\n\n2. Resolution probe + badges — every product card now shows a HD/MED/SD\n   badge in its top-right after the natural image dimensions are probed\n   client-side (concurrency 6, sessionStorage cached). Tier rules:\n     ≥ 1500 px largest side → HD (green)\n     ≥ 800  px              → MED (gold)\n     <  800  px             → SD (red)\n   SD cards fade to 55% opacity to push you toward HD picks.\n\n3. Hero panel banner — when a site is selected, a banner above the assigned-\n   collections section reports whether the current hero is HD/MED/SD with\n   the actual dimensions; SD shows a 'WILL LOOK BLURRY' warning.\n\n4. 'HD only' filter checkbox in the products bar — hides all non-HD cards.\n\n5. Products-bar count line now shows '23 HD · 12 MED · 4 SD · 8 probing'.\n\nCork live site already pushed with the upscale logic; 45 other sites\nre-patched locally pending deploy."},{"hash":"71f7337","date":"2026-05-06 17:42:44 -0700","author":"Steve","subject":"save+deploy: sort selector (textures/newest/title/sku/priceUp/priceDown/random) wired through API → renderSite; per CLAUDE.md grid sort+density rule","body":""},{"hash":"aa01c45","date":"2026-05-06 17:34:02 -0700","author":"SteveStudio2","subject":"Probe live HTTP status; flag redirected/parked sites in the grid","body":"Steve noticed several site cards showed wrong heroes — they're nginx 301/302\nredirects to consolidation domains, and the admin's screenshot probe was\nshowing the redirect target's hero. Misleading.\n\nThis change adds a HEAD probe + banner so consolidated sites are honest:\n\n- New POST /api/sites/probe — HEAD-checks every site over HTTPS, parallelism 8,\n  caches { http_status, redirect_target, probed_at } in data/site-status.json\n- listSites() merges the probe cache into each site row\n- index.html: new 📡 Probe live button in the toolbar; cards with 3xx render\n  a gold redirect banner overlaying the hero ('→ <target> (301)') AND fade\n  to 0.55 opacity so the redirect chain stops looking like a bug\n- Cards with HTTP 0/5xx render a red 'offline' banner\n\nVerified live: 46 sites probed in one click, 43 ok / 2 redirects (string→\nlinen, embroidered→fabric) / 1 offline. Banners render correctly."},{"hash":"3a36c5f","date":"2026-05-06 17:22:08 -0700","author":"SteveStudio2","subject":"Drag product → cover image + sort by color/style/SKU + grid-size slider","body":"Three new affordances on the right detail panel:\n\n1. Drag any product card onto the cover image to set it as the hero.\n   - .pcard is now draggable=true with a custom MIME (application/x-dwc-product)\n     carrying { sku, image, title }\n   - .hero-large catches dragover/drop, highlights via existing dropzone-active\n     CSS, then POSTs the sku to the existing /api/site/:slug/hero endpoint\n   - Optimistic local update + toast confirmation; renderDetail() re-renders\n     so the cover swaps without a fetch round-trip\n\n2. Sort dropdown — newest (default), Color (clusters black→white→warm→cool→\n   purple buckets via tag matching), Style (Traditional/Modern/Floral/etc.\n   buckets), SKU (alpha). Selection persists in localStorage as 'dwc_sort'.\n\n3. Grid card-width slider — 80px to 260px, live-updates\n   grid-template-columns:repeat(auto-fill,minmax(N,1fr)) without re-render.\n   Persists as 'dwc_size' in localStorage.\n\nVerified end-to-end via headless Playwright: 4-option sort dropdown live,\n50/50 cards draggable, drop simulation flips hero img src as expected."},{"hash":"f016e8f","date":"2026-05-06 17:17:29 -0700","author":"SteveStudio2","subject":"Click site → show all products as a responsive grid (was horizontal scroll)","body":"Previous .products-slider .row was a horizontal flex with 110px cards and\noverflow-x:auto — only ~6 cards visible at a time, lots of horizontal\nscrolling to see everything.\n\nNow: display:grid, grid-template-columns:repeat(auto-fill,minmax(140px,1fr)),\ngap:10px. Every product visible at once; cards bigger (140-200+ px) and\nlabels can wrap to 2 lines via -webkit-line-clamp:2 with min-height:32px so\nrows align. Selection, bulk-remove, copy SKUs all unchanged."},{"hash":"3f6faec","date":"2026-05-06 13:03:43 -0700","author":"SteveStudio2","subject":"bulk product remove-from-list (server endpoint + UI button)","body":""},{"hash":"8a47889","date":"2026-05-06 12:29:47 -0700","author":"SteveStudio2","subject":"press C anywhere to focus collection search input","body":""},{"hash":"7455efd","date":"2026-05-06 11:57:56 -0700","author":"SteveStudio2","subject":"show SKU + published_at in product card hover tooltip","body":""},{"hash":"3b2d32d","date":"2026-05-06 11:26:14 -0700","author":"SteveStudio2","subject":"color preview toast green/red by product-count delta","body":""},{"hash":"9c53f65","date":"2026-05-06 11:10:13 -0700","author":"SteveStudio2","subject":"add Save & Deploy combined button (one-click save + render + deploy)","body":""},{"hash":"0b73541","date":"2026-05-06 10:54:02 -0700","author":"Steve Abrams","subject":"add inline .env loader + Shopify pagination + all-products page","body":""},{"hash":"9a73dc0","date":"2026-05-06 10:20:19 -0700","author":"Steve Abrams","subject":"initial scaffold","body":""}]}