← back to Wallco Ai
luxe-curator: add canonical .when chip + flow created_at through /api/luxe-curator
7e3422988b33348b11517f1a674f553cb5b2cc37 · 2026-05-28 13:33:40 -0700 · Steve Abrams
Front-end (public/luxe-curator.html):
- Add .when chip (bottom-left of root tile) mirroring cactus-curator pattern:
🕓 ${fmtDate(p.created_at)} + ISO timestamp in title=.
- Add local fmtDate() helper (full year/month/day/hour/minute via toLocaleString).
- Add .when CSS rule (paired with the existing .ground bottom-right chip).
Server (server.js /api/luxe-curator):
- Capture the earliest log ts per root as created_at on the row object
(regen entries should not bump created_at forward).
- Include created_at in the response payload.
Closes tick-37 audit finding for luxe-curator (was the only "missing" surface;
"server.js change needed first" blocker resolved).
Files touched
M public/luxe-curator.htmlM server.js
Diff
commit 7e3422988b33348b11517f1a674f553cb5b2cc37
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Thu May 28 13:33:40 2026 -0700
luxe-curator: add canonical .when chip + flow created_at through /api/luxe-curator
Front-end (public/luxe-curator.html):
- Add .when chip (bottom-left of root tile) mirroring cactus-curator pattern:
🕓 ${fmtDate(p.created_at)} + ISO timestamp in title=.
- Add local fmtDate() helper (full year/month/day/hour/minute via toLocaleString).
- Add .when CSS rule (paired with the existing .ground bottom-right chip).
Server (server.js /api/luxe-curator):
- Capture the earliest log ts per root as created_at on the row object
(regen entries should not bump created_at forward).
- Include created_at in the response payload.
Closes tick-37 audit finding for luxe-curator (was the only "missing" surface;
"server.js change needed first" blocker resolved).
---
public/luxe-curator.html | 12 ++++++++++++
server.js | 10 +++++++++-
2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/public/luxe-curator.html b/public/luxe-curator.html
index 5aba62d..e85f761 100644
--- a/public/luxe-curator.html
+++ b/public/luxe-curator.html
@@ -55,6 +55,11 @@
letter-spacing:0.05em; background:rgba(255,255,255,0.92); color:#1a1a1a;
border-radius:2px; font-weight:600;
}
+ .row .tile .when {
+ position:absolute; bottom:6px; left:6px; padding:2px 6px; font-size:9.5px;
+ background:rgba(255,255,255,0.92); color:#1a1a1a; border-radius:2px;
+ font-weight:600; font-variant-numeric:tabular-nums; letter-spacing:.01em;
+ }
.row .tile .regen-btn {
position:absolute; top:6px; right:6px; width:24px; height:24px;
border-radius:50%; background:rgba(255,255,255,0.92); border:none;
@@ -116,6 +121,12 @@ async function loadData() {
return r.json();
}
+function fmtDate(iso) {
+ if (!iso) return '—';
+ const d = new Date(iso); if (isNaN(d)) return '—';
+ return d.toLocaleString(undefined, { year:'numeric', month:'short', day:'numeric', hour:'numeric', minute:'2-digit' });
+}
+
function toast(msg) {
const t = document.getElementById('toast');
t.textContent = msg;
@@ -146,6 +157,7 @@ function render() {
<div class="tile" data-pick="root" data-row="${i}" title="Keep root (don't publish any variant)">
<img loading="lazy" src="/designs/img/by-id/${p.root_id}?asis=1" alt="root ${p.root_id}">
<span class="label root">Root #${p.root_id}</span>
+ <span class="when" title="queued ${p.created_at||''}">🕓 ${fmtDate(p.created_at)}</span>
</div>
${variantTiles}
<div class="meta">
diff --git a/server.js b/server.js
index d55e522..4026c05 100644
--- a/server.js
+++ b/server.js
@@ -18186,13 +18186,20 @@ app.get('/api/luxe-curator', (req, res) => {
try {
const r = JSON.parse(line);
if (!r.ok || !r.new_id) continue;
- if (!byRoot.has(r.root_id)) byRoot.set(r.root_id, { root_id: r.root_id, motif: r.motif, variantMap: new Map() });
+ if (!byRoot.has(r.root_id)) byRoot.set(r.root_id, { root_id: r.root_id, motif: r.motif, variantMap: new Map(), created_at: r.ts || null });
// Overwrite previous entry for this variant — latest wins
byRoot.get(r.root_id).variantMap.set(r.variant, { variant: r.variant, new_id: r.new_id, ground: r.ground, duration_ms: r.duration_ms });
// Keep the longest motif we've seen — regen entries may have a truncated one
if (r.motif && r.motif.length > (byRoot.get(r.root_id).motif || '').length) {
byRoot.get(r.root_id).motif = r.motif;
}
+ // Keep the EARLIEST ts as the root's created_at — the moment this
+ // root was first queued for luxe-curator processing (regen entries
+ // are later by definition and should not bump created_at forward).
+ if (r.ts) {
+ const cur = byRoot.get(r.root_id).created_at;
+ if (!cur || r.ts < cur) byRoot.get(r.root_id).created_at = r.ts;
+ }
} catch {}
}
let decided = new Set();
@@ -18205,6 +18212,7 @@ app.get('/api/luxe-curator', (req, res) => {
.map(r => ({
root_id: r.root_id,
motif: r.motif,
+ created_at: r.created_at,
variants: [...r.variantMap.values()].sort((a, b) => a.variant.localeCompare(b.variant)),
}))
.sort((a, b) => a.root_id - b.root_id);
← e1b59d8 wallco.ai downloads route: /downloads/:slug/:token.zip token
·
back to Wallco Ai
·
strip Scenic/Studio sub-brand from customer-facing surfaces aed2aa0 →