{"slug":"customdigitalmurals","total":25,"limit":100,"offset":0,"since":null,"commits":[{"hash":"91fb733","date":"2026-06-23 09:50:52 -0700","author":"Steve Abrams","subject":"auto-save: 2026-06-23T09:50:51 (1 files) — server.js.tmp","body":""},{"hash":"70ea38b","date":"2026-06-21 16:57:33 -0700","author":"Steve","subject":"deploy: scaffold .deploy.conf for banner deploy","body":""},{"hash":"5e3ad01","date":"2026-06-21 16:48:56 -0700","author":"Steve","subject":"banner: wire universal promo-banner require above express.static (officer-approved; deploy gated)","body":""},{"hash":"7d37cef","date":"2026-06-04 08:08:10 -0700","author":"Steve","subject":"seo: add per-page canonical + Open Graph + Twitter card (headCommon threads canonical+ogImage; home + /product/:handle redacted slug)","body":""},{"hash":"13a98bb","date":"2026-06-03 20:44:30 -0700","author":"Steve","subject":"Scrub residual vendor names from products.json (title/vendor/tags); preserve sku/handle","body":""},{"hash":"929a23c","date":"2026-05-31 21:00:21 -0700","author":"Steve Abrams","subject":"render: route buy CTA + main-store anchor + card sample link through /buy/:slug (kill vendor-handle DOM leak; mirrors fleet a85eb02)","body":""},{"hash":"b4045d3","date":"2026-05-31 16:32:28 -0700","author":"Steve Abrams","subject":"Add per-site favicon (kills /favicon.ico 404)","body":""},{"hash":"4b85472","date":"2026-05-30 21:38:52 -0700","author":"Steve","subject":"scrub residual 3rd-party vendor names from products.json source (per sku-redact denylist; sku/handle + DW house brands preserved)","body":""},{"hash":"e7dffed","date":"2026-05-30 21:20:59 -0700","author":"Steve Abrams","subject":"fix: add /api/health alias so fleet-standard health probe returns 200","body":"The route was registered as /health only; /api/health returned 404.\nAdded /api/health as a second handler pointing at the same response\nto align with the DW fleet convention used by all sister sites.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>"},{"hash":"2047dc2","date":"2026-05-30 09:51:31 -0700","author":"Steve Abrams","subject":"fix: strip bare '-arte' (Arte International abbrev) from product slugs + sort denylist longest-first so 'arte international' strips before 'arte' (no 'international' residue). Closes residual leak from 2026-05-30 verify sweep.","body":""},{"hash":"301d03d","date":"2026-05-29 23:22:28 -0700","author":"Steve Abrams","subject":"reconcile: merge prod sort+density toolbar upgrade with the slug-leak fix (redactVendorSlug + dual-key route) — prod was ahead on sort, Mac2 ahead on fix; both now present. node -c OK","body":""},{"hash":"c0e645f","date":"2026-05-29 22:19:53 -0700","author":"Steve Abrams","subject":"fix: strip vendor tokens from product slug (redactVendorSlug) + dual-key route resolve — closes standalone slug vendor leak","body":""},{"hash":"c8239a8","date":"2026-05-28 07:25:52 -0700","author":"Steve","subject":"scrub vendor name leaks from products.json source (3132 products: title/vendor/tags cleaned per sku-redact denylist)","body":""},{"hash":"0aa321f","date":"2026-05-26 08:14:02 -0700","author":"Steve","subject":"homepage rails: 6 aesthetic rail sections + pills strip","body":"Adds /api/sliders endpoint, aesthetic filter on /api/products, aesthetic\ncounts on /api/facets. homePage() now renders 4 rail sections (green/\nbotanical/commercial/blue, 8 cards each, View all →) above the shop +\nhorizontal pill strip wired to setAesthetic(). Click any pill or 'View all'\nre-renders the grid filtered by that aesthetic and scrolls to #shop.\nPattern from hollywood-wallcoverings 3a7da85 + blockprintedwallpaper.\n\nBucket distribution: green 1638 / botanical 1537 / commercial 422 / blue\n24 / white 20 / architectural 14 (all 6 rails fire, all >= 4 items)."},{"hash":"55825b0","date":"2026-05-26 07:19:43 -0700","author":"Steve","subject":"wire api-vendor-redact middleware (close vendors-facet leak)","body":""},{"hash":"f60aec2","date":"2026-05-25 21:03:15 -0700","author":"Steve Abrams","subject":"remove vendor names from customer UI — replace with 'Designer Wallcoverings'","body":"DW rule: vendor names are admin-only metadata and must never appear on\ncustomer-facing surfaces (homepage cards, product pages, meta descriptions,\nJSON-LD brand). Removes the studio filter dropdown from the homepage toolbar\nand pins the card vendor line + product page brand line + Product schema brand\nto 'Designer Wallcoverings'. Server-side ?vendor= query and /api/vendors\nendpoint remain for admin / faceting; /api/facets exposes vendor counts as\nadmin metadata only."},{"hash":"7905e4b","date":"2026-05-25 21:01:33 -0700","author":"Steve Abrams","subject":"add /api/facets returning FILTERED counts (vendors + product_types); honors q + vendor query params","body":"Replaces the all-counts behavior with FILTERED counts so chip-style facet UIs\nreflect what selecting each option will actually return. Legacy /api/vendors\nkept for back-compat. Vendor names remain admin-only metadata — must not be\nrendered on customer-facing UI."},{"hash":"27a4699","date":"2026-05-25 20:37:35 -0700","author":"Steve Abrams","subject":"retag aesthetic from PG: 3663 rows updated","body":"before: <null>=3663\nafter:  all=8, architectural=14, blue=24, botanical=1537, commercial=422, green=1638, white=20\n\nBackfills correct multi-bucket aesthetic tagging from dw_unified.microsite_products\n(DTD verdict B, 2026-05-25 fleet retag run).\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"},{"hash":"24e237e","date":"2026-05-21 20:06:50 -0700","author":"Steve Abrams","subject":"make server.js self-contained — gate _shared/admin-catalog behind MICROSITE_ADMIN_ENABLED env flag (kamatera deploy unblock)","body":""},{"hash":"58bcf6a","date":"2026-05-19 15:14:41 -0700","author":"Steve Abrams","subject":"guard against serving .bak/.pre- snapshot files; widen .gitignore to match","body":"Adds a tiny middleware ahead of express.static that returns the 404 page for\nany URL path containing *.bak, *.bak.*, or .pre-* segments — so a backup file\naccidentally dropped into public/ can never leak to the open web. Widens\n.gitignore to keep those snapshot files out of the repo in the first place.\nNo bak/pre files are currently tracked; this is preventative.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"},{"hash":"58420cb","date":"2026-05-19 15:14:05 -0700","author":"Steve Abrams","subject":"add noreferrer to every target=_blank external link","body":"Four off-site links (DW footer, card sample CTA, product-page sample CTA,\nproduct-page DW deep-link) had rel=\"noopener\" but not noreferrer. Tabnabbing\nprotection without referrer leak prevention is half a fix; upgrade all four\nto rel=\"noopener noreferrer\" so the destination can't see the source URL on\nthe way in.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"},{"hash":"48db475","date":"2026-05-19 15:13:46 -0700","author":"Steve Abrams","subject":"sort + density persist to localStorage; hydrate before first grid load","body":"Standing rule: every product grid must persist sort + density selections to\nlocalStorage and rehydrate the saved value before the first grid load. The\nstorefront had the controls but neither persisted; refresh always reset to\nA-Z + density 4. Wires LS_SORT='cdm-sort' + LS_DENSITY='cdm-density' (matches\nthe existing cdm-theme key style), validates saved values against the rendered\noptions before applying, and updates the slider DOM value pre-mount so the\nfirst paint matches the user's last choice.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"},{"hash":"917bb01","date":"2026-05-19 11:29:18 -0700","author":"Steve Abrams","subject":"Phase 2: mobile-ready + tap-to-reveal","body":""},{"hash":"8e87abf","date":"2026-05-19 11:07:56 -0700","author":"Steve Abrams","subject":"stage2: wire customdigitalmurals onto shared catalog (hand-tailored)","body":""},{"hash":"31a4c17","date":"2026-05-07 15:00:06 -0700","author":"Steve Abrams","subject":"initial scaffold: customdigitalmurals.com Off-White storefront, 3663 products","body":""}]}