[object Object]

← back to Wallco Ai

wallco.ai · /sitemap.xml + /robots.txt — 233 URLs, saturation-weighted priority

3d1b6bd43d3f0269009de5ddb140ed103a5bfc30 · 2026-05-12 04:54:16 -0700 · SteveStudio2

Both were 404 before. Crawlers had no roadmap to the 228-design catalog.

robots.txt: allow all, disallow /admin/ + /api/ + /_devlogin, ref sitemap.
sitemap.xml: 5 static pages (/, /designs daily-1.0, /murals, /about, /provenance)
             + one entry per design (228 today). Priority = clamp(0.5 + 0.3*saturation
             + 0.1*has-room, 0.9). Top has-room saturated designs land at 0.77-0.83;
             baseline 0.5. lastmod from spoon_all_designs.created_at. 1h memory cache.

Reversible: two route handlers, no schema/storage changes.

Files touched

Diff

commit 3d1b6bd43d3f0269009de5ddb140ed103a5bfc30
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date:   Tue May 12 04:54:16 2026 -0700

    wallco.ai · /sitemap.xml + /robots.txt — 233 URLs, saturation-weighted priority
    
    Both were 404 before. Crawlers had no roadmap to the 228-design catalog.
    
    robots.txt: allow all, disallow /admin/ + /api/ + /_devlogin, ref sitemap.
    sitemap.xml: 5 static pages (/, /designs daily-1.0, /murals, /about, /provenance)
                 + one entry per design (228 today). Priority = clamp(0.5 + 0.3*saturation
                 + 0.1*has-room, 0.9). Top has-room saturated designs land at 0.77-0.83;
                 baseline 0.5. lastmod from spoon_all_designs.created_at. 1h memory cache.
    
    Reversible: two route handlers, no schema/storage changes.
---
 server.js | 44 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/server.js b/server.js
index a99d38a..27736bf 100644
--- a/server.js
+++ b/server.js
@@ -111,6 +111,50 @@ app.use('/designs/room', express.static(path.join(__dirname, 'data', 'rooms'), {
   setHeaders: (res) => res.setHeader('Cache-Control', 'public, max-age=604800')
 }));
 
+// ── robots.txt — allow all + reference the sitemap.
+app.get('/robots.txt', (req, res) => {
+  res.type('text/plain').send(
+    `User-agent: *\nAllow: /\nDisallow: /admin/\nDisallow: /api/\nDisallow: /_devlogin\n\nSitemap: https://${SITE}/sitemap.xml\n`
+  );
+});
+
+// ── sitemap.xml — static pages + every published design.
+// Priority ranks by saturation (more visually striking = better landing page);
+// designs with a room mockup get a +0.1 bonus capped at 0.9. Cached 1h.
+let SITEMAP_CACHE = { body: '', exp: 0 };
+app.get('/sitemap.xml', (req, res) => {
+  const now = Date.now();
+  if (SITEMAP_CACHE.body && SITEMAP_CACHE.exp > now) {
+    return res.type('application/xml').send(SITEMAP_CACHE.body);
+  }
+  const today = new Date().toISOString().slice(0, 10);
+  const staticPages = [
+    { loc: '/',          priority: '1.0', freq: 'daily'   },
+    { loc: '/designs',   priority: '0.9', freq: 'daily'   },
+    { loc: '/murals',    priority: '0.7', freq: 'weekly'  },
+    { loc: '/about',     priority: '0.5', freq: 'monthly' },
+    { loc: '/provenance',priority: '0.5', freq: 'monthly' },
+  ];
+  const urls = [];
+  for (const p of staticPages) {
+    urls.push(`  <url><loc>https://${SITE}${p.loc}</loc><changefreq>${p.freq}</changefreq><priority>${p.priority}</priority><lastmod>${today}</lastmod></url>`);
+  }
+  // Note: is_published is currently false for every row in designs.json (admin
+  // hasn't run the publish step yet) but /designs renders them all — so the
+  // sitemap mirrors the live catalog. If/when a "draft" flag is introduced,
+  // gate here.
+  for (const d of DESIGNS) {
+    const sat = Math.max(0, Math.min(1, Number(d.saturation) || 0));
+    const hasRoom = (d.room_mockups || []).length > 0 ? 0.1 : 0;
+    const prio = Math.min(0.9, 0.5 + 0.3 * sat + hasRoom).toFixed(2);
+    const lastmod = (d.created_at || '').slice(0, 10) || today;
+    urls.push(`  <url><loc>https://${SITE}/design/${d.id}</loc><changefreq>monthly</changefreq><priority>${prio}</priority><lastmod>${lastmod}</lastmod></url>`);
+  }
+  const xml = `<?xml version="1.0" encoding="UTF-8"?>\n<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n${urls.join('\n')}\n</urlset>\n`;
+  SITEMAP_CACHE = { body: xml, exp: now + 60 * 60 * 1000 };
+  res.type('application/xml').send(xml);
+});
+
 // ── Load design catalog (snapshot from DB — never stale-live Shopify)
 let DESIGNS = [];
 function loadDesigns() {

← 05812f4 wallco.ai · card-room-badge — dynamic room count ("4 rooms")  ·  back to Wallco Ai  ·  wallco.ai · /design/:id JSON-LD — enriched Product schema wi 149bfe0 →