[object Object]

← back to Thesetdecorator

TSD SEO: route /catalog through renderWithSEO (DTD verdict B)

38f6db1e693fc797fd8ef4ad5de0b1b2bdbe0dff · 2026-06-03 13:43:17 -0700 · Steve

The dedicated /catalog route did SSR-first-4-cards but bypassed renderWithSEO,
so /catalog served the WRONG canonical form (/catalog.html, missing the
loop-4 dedup) and had ZERO ItemList/Breadcrumb JSON-LD (dead code). Fix: call
renderWithSEO('catalog', req) for the SEO-injected HTML, then do the existing
marker card-replacement on it — the marker survives since renderWithSEO only
rewrites <head>. Verified on a free port: /catalog now has 1 clean canonical
(/catalog), ItemList+Breadcrumb (valid JSON), and the 4 SSR cards intact;
/catalog.html also canonicals to /catalog (one preferred URL). Inherits all
future renderWithSEO fixes. Resolves the loop-5 dead-code finding.

Files touched

Diff

commit 38f6db1e693fc797fd8ef4ad5de0b1b2bdbe0dff
Author: Steve <steve@designerwallcoverings.com>
Date:   Wed Jun 3 13:43:17 2026 -0700

    TSD SEO: route /catalog through renderWithSEO (DTD verdict B)
    
    The dedicated /catalog route did SSR-first-4-cards but bypassed renderWithSEO,
    so /catalog served the WRONG canonical form (/catalog.html, missing the
    loop-4 dedup) and had ZERO ItemList/Breadcrumb JSON-LD (dead code). Fix: call
    renderWithSEO('catalog', req) for the SEO-injected HTML, then do the existing
    marker card-replacement on it — the marker survives since renderWithSEO only
    rewrites <head>. Verified on a free port: /catalog now has 1 clean canonical
    (/catalog), ItemList+Breadcrumb (valid JSON), and the 4 SSR cards intact;
    /catalog.html also canonicals to /catalog (one preferred URL). Inherits all
    future renderWithSEO fixes. Resolves the loop-5 dead-code finding.
---
 server.js | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/server.js b/server.js
index 9e1dfa6..d4a1b9a 100644
--- a/server.js
+++ b/server.js
@@ -183,7 +183,14 @@ app.get(['/catalog.html', '/catalog'], (req, res, next) => {
   try {
     const filePath = path.join(ROOT, 'public', 'catalog.html');
     if (!fs.existsSync(filePath)) return next();
-    let html = fs.readFileSync(filePath, 'utf8');
+    // Route /catalog through renderWithSEO so the page gets the same clean
+    // (deduped) canonical + ItemList + Breadcrumb JSON-LD as every other public
+    // page — renderWithSEO('catalog') builds exactly that from the same seed and
+    // only rewrites <head>, so the <!--CATALOG_FIRST4_INJECT--> marker survives
+    // for the SSR-card replacement below. Falls back to the raw file if the
+    // SEO render is unavailable.
+    let html = renderWithSEO('catalog', req);
+    if (html == null) html = fs.readFileSync(filePath, 'utf8');
     if (!html.includes('<!--CATALOG_FIRST4_INJECT-->')) return next();
 
     const seedPath = path.join(ROOT, 'data', 'cleared-artwork-seed.json');

← 91035d1 backlog: mark deploy DONE — 8 SEO/a11y commits live + verifi  ·  back to Thesetdecorator  ·  backlog: catalog ItemList dead-code RESOLVED (38f6db1) — com 82a0b9b →