← 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 →