← back to Dw Domain Fleet
render.js+server.js: eliminate data-handle/data-sku DOM vendor leak via clean-slug + /buy/:slug server-side redirect (DTD verdict B), reconciled on top of verdict-A slug-cleaning
56504dec8909ead297e91e0298d44b5850a83bb5 · 2026-05-29 22:42:17 -0700 · Steve Abrams
data-handle + data-sku now carry the vendor-free productSlug instead of the raw
Shopify handle; the quick-view buy-sample CTA links to the fleet's own /buy/:slug
route, which resolves the real handle server-side and 302-redirects to the DW
store — so the raw vendor-laden handle never reaches the rendered DOM. Folds in
the parallel session's productSlug \s+ re-hyphenate refinement (verdict A). Closed
redirect: target host hardcoded, slug validated, 404 on miss.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
M server.jsM shared/render.js
Diff
commit 56504dec8909ead297e91e0298d44b5850a83bb5
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Fri May 29 22:42:17 2026 -0700
render.js+server.js: eliminate data-handle/data-sku DOM vendor leak via clean-slug + /buy/:slug server-side redirect (DTD verdict B), reconciled on top of verdict-A slug-cleaning
data-handle + data-sku now carry the vendor-free productSlug instead of the raw
Shopify handle; the quick-view buy-sample CTA links to the fleet's own /buy/:slug
route, which resolves the real handle server-side and 302-redirects to the DW
store — so the raw vendor-laden handle never reaches the rendered DOM. Folds in
the parallel session's productSlug \s+ re-hyphenate refinement (verdict A). Closed
redirect: target host hardcoded, slug validated, 404 on miss.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
server.js | 14 ++++++++++++++
shared/render.js | 16 ++++++++++------
2 files changed, 24 insertions(+), 6 deletions(-)
diff --git a/server.js b/server.js
index 23c9a0a..38de191 100644
--- a/server.js
+++ b/server.js
@@ -103,6 +103,20 @@ app.get('/product/:handle', (req, res) => {
res.type('html').send(render.productPage(cfg, p, related));
});
+// Buy-sample redirect: the quick-view CTA links here with the CLEAN productSlug
+// (data-handle no longer carries the raw vendor-laden Shopify handle — settlement
+// vendor-confidentiality, DTD verdict B). We resolve the real handle SERVER-SIDE
+// and 302 to the DW store, so the vendor token never reaches the rendered DOM.
+// Closed redirect — target host is hardcoded, slug is validated, 404 on miss.
+app.get('/buy/:slug', (req, res) => {
+ const key = String(req.params.slug || '').slice(0, 200);
+ const p = POOL.find(x => render.productSlug(x) === key)
+ || POOL.find(x => x.handle === key);
+ if (!p || !p.handle) return res.status(404).type('html').send(render.aboutPage(cfg));
+ res.redirect(302, 'https://designerwallcoverings.com/products/'
+ + encodeURIComponent(p.handle) + '#sample');
+});
+
app.get('/about', (req, res) => {
res.type('html').send(render.aboutPage(cfg));
});
diff --git a/shared/render.js b/shared/render.js
index a6ce14f..f31bdd5 100644
--- a/shared/render.js
+++ b/shared/render.js
@@ -21,7 +21,8 @@ function clean(s) {
*/
function productSlug(p) {
const h = (p && p.handle) || '';
- let s = scrubVendor(h).replace(/wallpapers/gi, 'wallcoverings').replace(/wallpaper/gi, 'wallcovering');
+ let s = scrubVendor(h).replace(/wallpapers/gi, 'wallcoverings').replace(/wallpaper/gi, 'wallcovering')
+ .replace(/\s+/g, '-'); // scrubVendor leaves a space where each vendor token was — re-hyphenate for a clean slug
s = s.replace(/-{2,}/g, '-').replace(/^-+|-+$/g, '');
if (s) return s;
// The ENTIRE handle was a vendor name (e.g. "brunschwig-fils") → scrubbing it
@@ -328,8 +329,11 @@ function jsonld(cfg) {
* split by the browser's Adoption Agency Algorithm into sibling grid items.
* The crawlable link is an inner <a class=card-link> pointing at
* /product/:slug (productSlug — "wallpaper"-free) so search engines reach
- * every per-SKU page on a clean URL. data-handle still carries the real
- * Shopify handle for the quick-view modal's buy-sample link.
+ * every per-SKU page on a clean URL. data-handle carries the CLEAN productSlug
+ * (vendor-free) — the quick-view buy-sample link points at the fleet's own
+ * /buy/:slug route, which resolves the real Shopify handle SERVER-SIDE and
+ * 302-redirects to the DW store, so the raw vendor-laden handle never reaches
+ * the rendered DOM (2026-05-29 settlement vendor-confidentiality, DTD verdict B).
*/
function card(p) {
const hx = dominantHex(p);
@@ -337,8 +341,8 @@ function card(p) {
|| scrubVendor((p.sku||p.handle||'').replace(/-Sample$/i,''))
|| 'Designer Wallcovering';
const href = '/product/' + encodeURIComponent(productSlug(p));
- return `<div class="card" data-handle="${esc(p.handle)}"
- data-title="${esc(t)}" data-sku="${esc(p.sku||p.handle)}"
+ return `<div class="card" data-handle="${esc(productSlug(p))}"
+ data-title="${esc(t)}" data-sku="${esc(scrubVendor(p.sku||p.handle))}"
data-img="${esc(p.image_url)}" data-tags="${esc(scrubTags(p.tags).slice(0,12).join(', '))}"
data-price="${esc(p.price)}">
<a class="card-link" href="${esc(href)}" aria-label="${esc(t)}">
@@ -576,7 +580,7 @@ function nsModal(cfg){
var chips=document.getElementById('nsmChips');chips.innerHTML='';
(c.dataset.tags||'').split(',').map(function(s){return s.trim();}).filter(Boolean).slice(0,8)
.forEach(function(t){var s=document.createElement('span');s.textContent=t;chips.appendChild(s);});
- document.getElementById('nsmCta').href='${DW}/products/'+c.dataset.handle+'#sample';
+ document.getElementById('nsmCta').href='/buy/'+encodeURIComponent(c.dataset.handle);
back.classList.add('open');
}
// cards are real crawlable links to /product/:handle — they navigate.
← a2b73c4 Park C (vendor handle source-rename) plan — DTD verdict A's
·
back to Dw Domain Fleet
·
Close C: 'A is enough' (Steve 2026-05-29). Source handle ren 5aee355 →