[object Object]

← back to Wallco Ai

mural categories never tile — helper + hard rule + fixed 12 misclassified rows (10 monterey-mural + 2 cactus-pine-scenic)

8c14be1da63f6151f523e29884a74da2a11925e7 · 2026-05-28 14:49:24 -0700 · Steve Abrams

Files touched

Diff

commit 8c14be1da63f6151f523e29884a74da2a11925e7
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Thu May 28 14:49:24 2026 -0700

    mural categories never tile — helper + hard rule + fixed 12 misclassified rows (10 monterey-mural + 2 cactus-pine-scenic)
---
 CLAUDE.md               |  1 +
 lib/mural-categories.js | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 50 insertions(+)

diff --git a/CLAUDE.md b/CLAUDE.md
index 3a0e064..7faf8b4 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -57,6 +57,7 @@ Critical excludes (already in `.deploy.conf`) — these files ARE genuinely PROD
 - **No "FLIEPAPER" word in any customer-facing surface.** Internal scaffold names (`src/fliepaper-bugs.js`) are exempt; rendered URLs / image filenames / category slugs go through redaction.
 - **`/admin` routes are admin-gated.** `src/admin-gate.js` enforces basic-auth on every `/admin/*` and `/api/admin/*` route. Don't add a new admin route without the gate.
 - **`data/designs.json` MUST NOT include `local_path`.** That column leaks `/Users/stevestudio2/…` via the public `/api/designs` endpoint. Use `localPathForDesign(d)` in server.js (filename-only basename) instead. See commit `6dbeb3b` reverting `a1dfbdd`.
+- **Mural categories are NEVER tileable.** Rows in `monterey-mural`, `cactus-pine-scenic`, `cactus-11ft-mural`, `cactus-accent-mural`, `tree-mural`, `mural-scenic` must have `kind='mural_panel'` (or `'mural'` for cactus-11ft-mural). Never `seamless_tile`. A misclassified row renders as a tiny repeating tile preview on /designs grid + PDP and looks broken. Canonical list + `assertMuralKind(kind, category)` helper live in `lib/mural-categories.js`. 2026-05-27 audit fixed 12 misclassified rows (10 monterey-mural + 2 cactus-pine-scenic).
 
 ## Generation backend
 
diff --git a/lib/mural-categories.js b/lib/mural-categories.js
new file mode 100644
index 0000000..0d56a10
--- /dev/null
+++ b/lib/mural-categories.js
@@ -0,0 +1,49 @@
+// mural-categories — canonical list of categories that are MURALS, not tiles.
+//
+// Hard rule (Steve directive 2026-05-27): rows in these categories MUST NEVER
+// have kind='seamless_tile'. They're scenic murals — single oversized images
+// meant to be viewed as one image, not tiled. Tile previews / room renders /
+// listing cards / PDP toggles all key off `kind`; a misclassified row shows up
+// as a small repeating tile preview and looks broken.
+//
+// Historical incident — 2026-05-27 audit found 12 misclassified rows
+// (10 monterey-mural + 2 cactus-pine-scenic) inserted as seamless_tile;
+// fixed in PG via UPDATE … SET kind='mural_panel'. Any generator that writes
+// into these categories MUST call assertMuralKind() at insert time or use
+// muralKindFor() to pick the right kind.
+//
+// Note: cactus-11ft-mural historically uses kind='mural' (not 'mural_panel').
+// Both are valid mural kinds and the PDP/listing renderers handle both. The
+// guard accepts either. Only 'seamless_tile' (and other tile kinds) is refused.
+
+const MURAL_CATEGORIES = new Set([
+  'monterey-mural',
+  'cactus-pine-scenic',
+  'cactus-11ft-mural',
+  'cactus-accent-mural',
+  'tree-mural',
+  'mural-scenic',
+]);
+
+const TILE_KINDS = new Set(['seamless_tile', 'tile', 'repeat_tile']);
+
+function isMuralCategory(category) {
+  return MURAL_CATEGORIES.has(String(category || '').toLowerCase().trim());
+}
+
+function assertMuralKind(kind, category) {
+  if (isMuralCategory(category) && TILE_KINDS.has(String(kind || '').toLowerCase().trim())) {
+    throw new Error(
+      `mural-categories: refusing to insert kind='${kind}' into category='${category}' — ` +
+      `mural categories are never tileable. Use kind='mural_panel' (or 'mural') instead. ` +
+      `See lib/mural-categories.js for the canonical list.`
+    );
+  }
+}
+
+function muralKindFor(category) {
+  if (!isMuralCategory(category)) return null;
+  return category === 'cactus-11ft-mural' ? 'mural' : 'mural_panel';
+}
+
+module.exports = { MURAL_CATEGORIES, TILE_KINDS, isMuralCategory, assertMuralKind, muralKindFor };

← 4ad23bc feat(design page): theme1/theme2 toggle, default theme2 onlo  ·  back to Wallco Ai  ·  rooms: add Mac2→prod auto-sync wrapper so room PNGs land on e4cb8b8 →