← back to Wallco Ai
wallco.ai · /api/designs/random?n=12&category=&seed= — random sample for 'Surprise me' rails + empty-state discovery · partial Fisher-Yates (O(n) not O(N)) · optional ?category= filter, optional ?seed= mulberry32 PRNG for reproducible shuffles · Cache-Control:no-store (randomness is the point) · verified: n=3→228-pool, category=floral→17-pool, seed=42→deterministic [208,173,265]
817e1364f14e61e70aeeb9f9a2daf7cdb0fb5917 · 2026-05-12 08:23:45 -0700 · SteveStudio2
Files touched
Diff
commit 817e1364f14e61e70aeeb9f9a2daf7cdb0fb5917
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date: Tue May 12 08:23:45 2026 -0700
wallco.ai · /api/designs/random?n=12&category=&seed= — random sample for 'Surprise me' rails + empty-state discovery · partial Fisher-Yates (O(n) not O(N)) · optional ?category= filter, optional ?seed= mulberry32 PRNG for reproducible shuffles · Cache-Control:no-store (randomness is the point) · verified: n=3→228-pool, category=floral→17-pool, seed=42→deterministic [208,173,265]
---
server.js | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)
diff --git a/server.js b/server.js
index 898cc72..36dd5dc 100644
--- a/server.js
+++ b/server.js
@@ -294,6 +294,60 @@ app.get('/api/designs/search', (req, res) => {
});
});
+// ── /api/designs/random?n=12&category=floral&seed=42
+// Returns N random designs. Useful for "Surprise me" rails + empty-state discovery.
+// Optional ?category= filter. Optional ?seed= for reproducible shuffles (otherwise time-seeded).
+// Cache-Control: no-store — randomness is the point; caching defeats it.
+app.get('/api/designs/random', (req, res) => {
+ const n = Math.max(1, Math.min(50, parseInt(req.query.n || '12', 10)));
+ const category = String(req.query.category || '').toLowerCase().trim();
+ const seedRaw = req.query.seed;
+ const pool = category
+ ? DESIGNS.filter(d => (d.category || '').toLowerCase() === category)
+ : DESIGNS.slice();
+ // Deterministic seeded PRNG (mulberry32) if seed provided; else Math.random.
+ let rand;
+ if (seedRaw !== undefined && seedRaw !== '') {
+ let s = parseInt(seedRaw, 10) >>> 0;
+ rand = function() {
+ s |= 0; s = (s + 0x6D2B79F5) | 0;
+ let t = s;
+ t = Math.imul(t ^ (t >>> 15), t | 1);
+ t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
+ return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
+ };
+ } else {
+ rand = Math.random;
+ }
+ // Partial Fisher-Yates — picks first N positions of shuffle without touching the rest.
+ const sample = [];
+ const idx = pool.map((_, i) => i);
+ const k = Math.min(n, idx.length);
+ for (let i = 0; i < k; i++) {
+ const j = i + Math.floor(rand() * (idx.length - i));
+ [idx[i], idx[j]] = [idx[j], idx[i]];
+ const d = pool[idx[i]];
+ sample.push({
+ id: d.id,
+ title: d.title,
+ category: d.category,
+ handle: d.handle,
+ image_url: d.image_url,
+ dominant_hex: d.dominant_hex,
+ room_mockups: d.room_mockups || [],
+ url: `/design/${d.id}`,
+ });
+ }
+ res.setHeader('Cache-Control', 'no-store');
+ res.json({
+ n: k,
+ pool_size: pool.length,
+ category: category || null,
+ seed: seedRaw !== undefined && seedRaw !== '' ? parseInt(seedRaw,10) : null,
+ results: sample,
+ });
+});
+
// ── Color sort helpers
function hexToHSL(hex) {
if (!hex) return [0, 0, 0.5];
← 340a3c9 wallco.ai · autocomplete dropdown now renders a 'Refine' mot
·
back to Wallco Ai
·
wallco.ai · empty /compare now renders a 'More designs to ex fe60c05 →