← back to Quadrille Showroom
auto-save: 2026-06-28T09:43:58 (3 files) — public/js/showroom.js server.js data/thumb-cache/
61fe1e273d6d56416b7687a29a33aff5cfba7fc9 · 2026-06-28 09:44:01 -0700 · Steve Abrams
Files touched
A data/thumb-cache/099160b17f710e570c5aa9ac.jpgA data/thumb-cache/0b9c68a67796dd1ccce90a5a.jpgA data/thumb-cache/263e90a8e86b9099564d880f.jpgA data/thumb-cache/2ae01b0b7d1fd04c00fdf66d.jpgA data/thumb-cache/2ba7e03368ff27763d2ef6a1.jpgA data/thumb-cache/2fbfa15f2853f912623aed15.jpgA data/thumb-cache/3cc44c54cb55798449090548.jpgA data/thumb-cache/3f441bb0f30a6e1d2e049c99.jpgA data/thumb-cache/44fbcf466a13d44c920bf876.jpgA data/thumb-cache/48d8be87436cc93bf2c43e97.jpgA data/thumb-cache/4a03f0dff059f9cb74a8f68b.jpgA data/thumb-cache/5e1bde985d0a6b5cc21f78e8.jpgA data/thumb-cache/6ac3f77fa6efe0dbca83526e.jpgA data/thumb-cache/6de50aa4eecf76ec8b46608f.jpgA data/thumb-cache/7003563012c91195ea481f8f.jpgA data/thumb-cache/7174d03da23235f90f17ff7b.jpgA data/thumb-cache/79e9655d90d2707d0f3cc98c.jpgA data/thumb-cache/7ee3f79366d62966a5295da4.jpgA data/thumb-cache/83bf2a3012a67ceae0264aa9.jpgA data/thumb-cache/8e080de9798485fa3badb5f6.jpgA data/thumb-cache/90b97a1dae394bf1bd6d4902.jpgA data/thumb-cache/9231e0fba1551d50554f2e92.jpgA data/thumb-cache/946174e77373830644fdcce4.jpgA data/thumb-cache/962c93a220c69af4f237020e.jpgA data/thumb-cache/a575f374084aef6f484e37e0.jpgA data/thumb-cache/aa0a9191f35c84434c33b570.jpgA data/thumb-cache/ab3c0d5c3b90d148bb357ac9.jpgA data/thumb-cache/ac0ed992279779cadf9c433c.jpgA data/thumb-cache/ad86a76bc4444c833d22c5bc.jpgA data/thumb-cache/b31fac5aa5f543e812424505.jpgA data/thumb-cache/b692f428447edc40905a2004.jpgA data/thumb-cache/b77ee76df67378944ef41b72.jpgA data/thumb-cache/bb60ef27cefed3b5da7c243e.jpgA data/thumb-cache/bf1537e14a5bbcd16b6927b0.jpgA data/thumb-cache/c081b75ff0d0981452933ea8.jpgA data/thumb-cache/c6c585cdffa240943d9ed183.jpgA data/thumb-cache/c8f0693350b1df2a1926bec0.jpgA data/thumb-cache/cb421f06cd11e014ecb53cbd.jpgA data/thumb-cache/d38d6ade32f93a27bf1e720c.jpgA data/thumb-cache/d549f8a7ec69ed6523a12bcc.jpgA data/thumb-cache/d6b094caae0de0ba16eea5db.jpgA data/thumb-cache/d9462876e1e7c57a8d51e235.jpgA data/thumb-cache/de14e7e731878c255eecddb4.jpgA data/thumb-cache/ded5027936e45e8f614fe792.jpgA data/thumb-cache/e3d05b503f89a0a1ff8ed456.jpgA data/thumb-cache/e934fd973f3fbcc4acc0f809.jpgA data/thumb-cache/eb550c8e11ad1aa92c6c6c79.jpgA data/thumb-cache/f551b80de266aad6e43aead7.jpgM public/js/showroom.jsM server.js
Diff
commit 61fe1e273d6d56416b7687a29a33aff5cfba7fc9
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Sun Jun 28 09:44:01 2026 -0700
auto-save: 2026-06-28T09:43:58 (3 files) — public/js/showroom.js server.js data/thumb-cache/
---
data/thumb-cache/099160b17f710e570c5aa9ac.jpg | Bin 0 -> 7955 bytes
data/thumb-cache/0b9c68a67796dd1ccce90a5a.jpg | Bin 0 -> 5346 bytes
data/thumb-cache/263e90a8e86b9099564d880f.jpg | Bin 0 -> 8747 bytes
data/thumb-cache/2ae01b0b7d1fd04c00fdf66d.jpg | Bin 0 -> 10015 bytes
data/thumb-cache/2ba7e03368ff27763d2ef6a1.jpg | Bin 0 -> 5457 bytes
data/thumb-cache/2fbfa15f2853f912623aed15.jpg | Bin 0 -> 9614 bytes
data/thumb-cache/3cc44c54cb55798449090548.jpg | Bin 0 -> 10292 bytes
data/thumb-cache/3f441bb0f30a6e1d2e049c99.jpg | Bin 0 -> 6804 bytes
data/thumb-cache/44fbcf466a13d44c920bf876.jpg | Bin 0 -> 5683 bytes
data/thumb-cache/48d8be87436cc93bf2c43e97.jpg | Bin 0 -> 11086 bytes
data/thumb-cache/4a03f0dff059f9cb74a8f68b.jpg | Bin 0 -> 5606 bytes
data/thumb-cache/5e1bde985d0a6b5cc21f78e8.jpg | Bin 0 -> 10478 bytes
data/thumb-cache/6ac3f77fa6efe0dbca83526e.jpg | Bin 0 -> 7271 bytes
data/thumb-cache/6de50aa4eecf76ec8b46608f.jpg | Bin 0 -> 8106 bytes
data/thumb-cache/7003563012c91195ea481f8f.jpg | Bin 0 -> 11785 bytes
data/thumb-cache/7174d03da23235f90f17ff7b.jpg | Bin 0 -> 13073 bytes
data/thumb-cache/79e9655d90d2707d0f3cc98c.jpg | Bin 0 -> 6036 bytes
data/thumb-cache/7ee3f79366d62966a5295da4.jpg | Bin 0 -> 7253 bytes
data/thumb-cache/83bf2a3012a67ceae0264aa9.jpg | Bin 0 -> 7125 bytes
data/thumb-cache/8e080de9798485fa3badb5f6.jpg | Bin 0 -> 6499 bytes
data/thumb-cache/90b97a1dae394bf1bd6d4902.jpg | Bin 0 -> 5544 bytes
data/thumb-cache/9231e0fba1551d50554f2e92.jpg | Bin 0 -> 9975 bytes
data/thumb-cache/946174e77373830644fdcce4.jpg | Bin 0 -> 5357 bytes
data/thumb-cache/962c93a220c69af4f237020e.jpg | Bin 0 -> 6684 bytes
data/thumb-cache/a575f374084aef6f484e37e0.jpg | Bin 0 -> 7643 bytes
data/thumb-cache/aa0a9191f35c84434c33b570.jpg | Bin 0 -> 9866 bytes
data/thumb-cache/ab3c0d5c3b90d148bb357ac9.jpg | Bin 0 -> 7221 bytes
data/thumb-cache/ac0ed992279779cadf9c433c.jpg | Bin 0 -> 11518 bytes
data/thumb-cache/ad86a76bc4444c833d22c5bc.jpg | Bin 0 -> 10517 bytes
data/thumb-cache/b31fac5aa5f543e812424505.jpg | Bin 0 -> 11915 bytes
data/thumb-cache/b692f428447edc40905a2004.jpg | Bin 0 -> 9654 bytes
data/thumb-cache/b77ee76df67378944ef41b72.jpg | Bin 0 -> 6854 bytes
data/thumb-cache/bb60ef27cefed3b5da7c243e.jpg | Bin 0 -> 11788 bytes
data/thumb-cache/bf1537e14a5bbcd16b6927b0.jpg | Bin 0 -> 6446 bytes
data/thumb-cache/c081b75ff0d0981452933ea8.jpg | Bin 0 -> 6524 bytes
data/thumb-cache/c6c585cdffa240943d9ed183.jpg | Bin 0 -> 9112 bytes
data/thumb-cache/c8f0693350b1df2a1926bec0.jpg | Bin 0 -> 7369 bytes
data/thumb-cache/cb421f06cd11e014ecb53cbd.jpg | Bin 0 -> 8840 bytes
data/thumb-cache/d38d6ade32f93a27bf1e720c.jpg | Bin 0 -> 13188 bytes
data/thumb-cache/d549f8a7ec69ed6523a12bcc.jpg | Bin 0 -> 6048 bytes
data/thumb-cache/d6b094caae0de0ba16eea5db.jpg | Bin 0 -> 11649 bytes
data/thumb-cache/d9462876e1e7c57a8d51e235.jpg | Bin 0 -> 7492 bytes
data/thumb-cache/de14e7e731878c255eecddb4.jpg | Bin 0 -> 11850 bytes
data/thumb-cache/ded5027936e45e8f614fe792.jpg | Bin 0 -> 7760 bytes
data/thumb-cache/e3d05b503f89a0a1ff8ed456.jpg | Bin 0 -> 6359 bytes
data/thumb-cache/e934fd973f3fbcc4acc0f809.jpg | Bin 0 -> 12969 bytes
data/thumb-cache/eb550c8e11ad1aa92c6c6c79.jpg | Bin 0 -> 4056 bytes
data/thumb-cache/f551b80de266aad6e43aead7.jpg | Bin 0 -> 12252 bytes
public/js/showroom.js | 30 +++++++----
server.js | 75 ++++++++++++++++++++++++++
50 files changed, 94 insertions(+), 11 deletions(-)
diff --git a/data/thumb-cache/099160b17f710e570c5aa9ac.jpg b/data/thumb-cache/099160b17f710e570c5aa9ac.jpg
new file mode 100644
index 0000000..c6a5012
Binary files /dev/null and b/data/thumb-cache/099160b17f710e570c5aa9ac.jpg differ
diff --git a/data/thumb-cache/0b9c68a67796dd1ccce90a5a.jpg b/data/thumb-cache/0b9c68a67796dd1ccce90a5a.jpg
new file mode 100644
index 0000000..4eeb7e9
Binary files /dev/null and b/data/thumb-cache/0b9c68a67796dd1ccce90a5a.jpg differ
diff --git a/data/thumb-cache/263e90a8e86b9099564d880f.jpg b/data/thumb-cache/263e90a8e86b9099564d880f.jpg
new file mode 100644
index 0000000..25671e1
Binary files /dev/null and b/data/thumb-cache/263e90a8e86b9099564d880f.jpg differ
diff --git a/data/thumb-cache/2ae01b0b7d1fd04c00fdf66d.jpg b/data/thumb-cache/2ae01b0b7d1fd04c00fdf66d.jpg
new file mode 100644
index 0000000..00975b8
Binary files /dev/null and b/data/thumb-cache/2ae01b0b7d1fd04c00fdf66d.jpg differ
diff --git a/data/thumb-cache/2ba7e03368ff27763d2ef6a1.jpg b/data/thumb-cache/2ba7e03368ff27763d2ef6a1.jpg
new file mode 100644
index 0000000..77052ce
Binary files /dev/null and b/data/thumb-cache/2ba7e03368ff27763d2ef6a1.jpg differ
diff --git a/data/thumb-cache/2fbfa15f2853f912623aed15.jpg b/data/thumb-cache/2fbfa15f2853f912623aed15.jpg
new file mode 100644
index 0000000..e7696f5
Binary files /dev/null and b/data/thumb-cache/2fbfa15f2853f912623aed15.jpg differ
diff --git a/data/thumb-cache/3cc44c54cb55798449090548.jpg b/data/thumb-cache/3cc44c54cb55798449090548.jpg
new file mode 100644
index 0000000..2b85bcb
Binary files /dev/null and b/data/thumb-cache/3cc44c54cb55798449090548.jpg differ
diff --git a/data/thumb-cache/3f441bb0f30a6e1d2e049c99.jpg b/data/thumb-cache/3f441bb0f30a6e1d2e049c99.jpg
new file mode 100644
index 0000000..dedc65b
Binary files /dev/null and b/data/thumb-cache/3f441bb0f30a6e1d2e049c99.jpg differ
diff --git a/data/thumb-cache/44fbcf466a13d44c920bf876.jpg b/data/thumb-cache/44fbcf466a13d44c920bf876.jpg
new file mode 100644
index 0000000..b4b347f
Binary files /dev/null and b/data/thumb-cache/44fbcf466a13d44c920bf876.jpg differ
diff --git a/data/thumb-cache/48d8be87436cc93bf2c43e97.jpg b/data/thumb-cache/48d8be87436cc93bf2c43e97.jpg
new file mode 100644
index 0000000..66f0bd2
Binary files /dev/null and b/data/thumb-cache/48d8be87436cc93bf2c43e97.jpg differ
diff --git a/data/thumb-cache/4a03f0dff059f9cb74a8f68b.jpg b/data/thumb-cache/4a03f0dff059f9cb74a8f68b.jpg
new file mode 100644
index 0000000..291b046
Binary files /dev/null and b/data/thumb-cache/4a03f0dff059f9cb74a8f68b.jpg differ
diff --git a/data/thumb-cache/5e1bde985d0a6b5cc21f78e8.jpg b/data/thumb-cache/5e1bde985d0a6b5cc21f78e8.jpg
new file mode 100644
index 0000000..1a01b62
Binary files /dev/null and b/data/thumb-cache/5e1bde985d0a6b5cc21f78e8.jpg differ
diff --git a/data/thumb-cache/6ac3f77fa6efe0dbca83526e.jpg b/data/thumb-cache/6ac3f77fa6efe0dbca83526e.jpg
new file mode 100644
index 0000000..f593e54
Binary files /dev/null and b/data/thumb-cache/6ac3f77fa6efe0dbca83526e.jpg differ
diff --git a/data/thumb-cache/6de50aa4eecf76ec8b46608f.jpg b/data/thumb-cache/6de50aa4eecf76ec8b46608f.jpg
new file mode 100644
index 0000000..665bbd9
Binary files /dev/null and b/data/thumb-cache/6de50aa4eecf76ec8b46608f.jpg differ
diff --git a/data/thumb-cache/7003563012c91195ea481f8f.jpg b/data/thumb-cache/7003563012c91195ea481f8f.jpg
new file mode 100644
index 0000000..5198415
Binary files /dev/null and b/data/thumb-cache/7003563012c91195ea481f8f.jpg differ
diff --git a/data/thumb-cache/7174d03da23235f90f17ff7b.jpg b/data/thumb-cache/7174d03da23235f90f17ff7b.jpg
new file mode 100644
index 0000000..44de402
Binary files /dev/null and b/data/thumb-cache/7174d03da23235f90f17ff7b.jpg differ
diff --git a/data/thumb-cache/79e9655d90d2707d0f3cc98c.jpg b/data/thumb-cache/79e9655d90d2707d0f3cc98c.jpg
new file mode 100644
index 0000000..f6243d7
Binary files /dev/null and b/data/thumb-cache/79e9655d90d2707d0f3cc98c.jpg differ
diff --git a/data/thumb-cache/7ee3f79366d62966a5295da4.jpg b/data/thumb-cache/7ee3f79366d62966a5295da4.jpg
new file mode 100644
index 0000000..5dcd4d0
Binary files /dev/null and b/data/thumb-cache/7ee3f79366d62966a5295da4.jpg differ
diff --git a/data/thumb-cache/83bf2a3012a67ceae0264aa9.jpg b/data/thumb-cache/83bf2a3012a67ceae0264aa9.jpg
new file mode 100644
index 0000000..a7071d2
Binary files /dev/null and b/data/thumb-cache/83bf2a3012a67ceae0264aa9.jpg differ
diff --git a/data/thumb-cache/8e080de9798485fa3badb5f6.jpg b/data/thumb-cache/8e080de9798485fa3badb5f6.jpg
new file mode 100644
index 0000000..07e170f
Binary files /dev/null and b/data/thumb-cache/8e080de9798485fa3badb5f6.jpg differ
diff --git a/data/thumb-cache/90b97a1dae394bf1bd6d4902.jpg b/data/thumb-cache/90b97a1dae394bf1bd6d4902.jpg
new file mode 100644
index 0000000..796cf60
Binary files /dev/null and b/data/thumb-cache/90b97a1dae394bf1bd6d4902.jpg differ
diff --git a/data/thumb-cache/9231e0fba1551d50554f2e92.jpg b/data/thumb-cache/9231e0fba1551d50554f2e92.jpg
new file mode 100644
index 0000000..70da98c
Binary files /dev/null and b/data/thumb-cache/9231e0fba1551d50554f2e92.jpg differ
diff --git a/data/thumb-cache/946174e77373830644fdcce4.jpg b/data/thumb-cache/946174e77373830644fdcce4.jpg
new file mode 100644
index 0000000..2287228
Binary files /dev/null and b/data/thumb-cache/946174e77373830644fdcce4.jpg differ
diff --git a/data/thumb-cache/962c93a220c69af4f237020e.jpg b/data/thumb-cache/962c93a220c69af4f237020e.jpg
new file mode 100644
index 0000000..5914d57
Binary files /dev/null and b/data/thumb-cache/962c93a220c69af4f237020e.jpg differ
diff --git a/data/thumb-cache/a575f374084aef6f484e37e0.jpg b/data/thumb-cache/a575f374084aef6f484e37e0.jpg
new file mode 100644
index 0000000..c22c066
Binary files /dev/null and b/data/thumb-cache/a575f374084aef6f484e37e0.jpg differ
diff --git a/data/thumb-cache/aa0a9191f35c84434c33b570.jpg b/data/thumb-cache/aa0a9191f35c84434c33b570.jpg
new file mode 100644
index 0000000..4a95a45
Binary files /dev/null and b/data/thumb-cache/aa0a9191f35c84434c33b570.jpg differ
diff --git a/data/thumb-cache/ab3c0d5c3b90d148bb357ac9.jpg b/data/thumb-cache/ab3c0d5c3b90d148bb357ac9.jpg
new file mode 100644
index 0000000..139cdf2
Binary files /dev/null and b/data/thumb-cache/ab3c0d5c3b90d148bb357ac9.jpg differ
diff --git a/data/thumb-cache/ac0ed992279779cadf9c433c.jpg b/data/thumb-cache/ac0ed992279779cadf9c433c.jpg
new file mode 100644
index 0000000..16a49eb
Binary files /dev/null and b/data/thumb-cache/ac0ed992279779cadf9c433c.jpg differ
diff --git a/data/thumb-cache/ad86a76bc4444c833d22c5bc.jpg b/data/thumb-cache/ad86a76bc4444c833d22c5bc.jpg
new file mode 100644
index 0000000..4d51801
Binary files /dev/null and b/data/thumb-cache/ad86a76bc4444c833d22c5bc.jpg differ
diff --git a/data/thumb-cache/b31fac5aa5f543e812424505.jpg b/data/thumb-cache/b31fac5aa5f543e812424505.jpg
new file mode 100644
index 0000000..b279f67
Binary files /dev/null and b/data/thumb-cache/b31fac5aa5f543e812424505.jpg differ
diff --git a/data/thumb-cache/b692f428447edc40905a2004.jpg b/data/thumb-cache/b692f428447edc40905a2004.jpg
new file mode 100644
index 0000000..bf5e59b
Binary files /dev/null and b/data/thumb-cache/b692f428447edc40905a2004.jpg differ
diff --git a/data/thumb-cache/b77ee76df67378944ef41b72.jpg b/data/thumb-cache/b77ee76df67378944ef41b72.jpg
new file mode 100644
index 0000000..a8267c7
Binary files /dev/null and b/data/thumb-cache/b77ee76df67378944ef41b72.jpg differ
diff --git a/data/thumb-cache/bb60ef27cefed3b5da7c243e.jpg b/data/thumb-cache/bb60ef27cefed3b5da7c243e.jpg
new file mode 100644
index 0000000..d501eff
Binary files /dev/null and b/data/thumb-cache/bb60ef27cefed3b5da7c243e.jpg differ
diff --git a/data/thumb-cache/bf1537e14a5bbcd16b6927b0.jpg b/data/thumb-cache/bf1537e14a5bbcd16b6927b0.jpg
new file mode 100644
index 0000000..b2b0d9d
Binary files /dev/null and b/data/thumb-cache/bf1537e14a5bbcd16b6927b0.jpg differ
diff --git a/data/thumb-cache/c081b75ff0d0981452933ea8.jpg b/data/thumb-cache/c081b75ff0d0981452933ea8.jpg
new file mode 100644
index 0000000..8ced84a
Binary files /dev/null and b/data/thumb-cache/c081b75ff0d0981452933ea8.jpg differ
diff --git a/data/thumb-cache/c6c585cdffa240943d9ed183.jpg b/data/thumb-cache/c6c585cdffa240943d9ed183.jpg
new file mode 100644
index 0000000..a989251
Binary files /dev/null and b/data/thumb-cache/c6c585cdffa240943d9ed183.jpg differ
diff --git a/data/thumb-cache/c8f0693350b1df2a1926bec0.jpg b/data/thumb-cache/c8f0693350b1df2a1926bec0.jpg
new file mode 100644
index 0000000..0a0b6f2
Binary files /dev/null and b/data/thumb-cache/c8f0693350b1df2a1926bec0.jpg differ
diff --git a/data/thumb-cache/cb421f06cd11e014ecb53cbd.jpg b/data/thumb-cache/cb421f06cd11e014ecb53cbd.jpg
new file mode 100644
index 0000000..e3af55a
Binary files /dev/null and b/data/thumb-cache/cb421f06cd11e014ecb53cbd.jpg differ
diff --git a/data/thumb-cache/d38d6ade32f93a27bf1e720c.jpg b/data/thumb-cache/d38d6ade32f93a27bf1e720c.jpg
new file mode 100644
index 0000000..b8606d5
Binary files /dev/null and b/data/thumb-cache/d38d6ade32f93a27bf1e720c.jpg differ
diff --git a/data/thumb-cache/d549f8a7ec69ed6523a12bcc.jpg b/data/thumb-cache/d549f8a7ec69ed6523a12bcc.jpg
new file mode 100644
index 0000000..6b9fa43
Binary files /dev/null and b/data/thumb-cache/d549f8a7ec69ed6523a12bcc.jpg differ
diff --git a/data/thumb-cache/d6b094caae0de0ba16eea5db.jpg b/data/thumb-cache/d6b094caae0de0ba16eea5db.jpg
new file mode 100644
index 0000000..2a6e4c8
Binary files /dev/null and b/data/thumb-cache/d6b094caae0de0ba16eea5db.jpg differ
diff --git a/data/thumb-cache/d9462876e1e7c57a8d51e235.jpg b/data/thumb-cache/d9462876e1e7c57a8d51e235.jpg
new file mode 100644
index 0000000..6e4401d
Binary files /dev/null and b/data/thumb-cache/d9462876e1e7c57a8d51e235.jpg differ
diff --git a/data/thumb-cache/de14e7e731878c255eecddb4.jpg b/data/thumb-cache/de14e7e731878c255eecddb4.jpg
new file mode 100644
index 0000000..1610e0b
Binary files /dev/null and b/data/thumb-cache/de14e7e731878c255eecddb4.jpg differ
diff --git a/data/thumb-cache/ded5027936e45e8f614fe792.jpg b/data/thumb-cache/ded5027936e45e8f614fe792.jpg
new file mode 100644
index 0000000..2352cf3
Binary files /dev/null and b/data/thumb-cache/ded5027936e45e8f614fe792.jpg differ
diff --git a/data/thumb-cache/e3d05b503f89a0a1ff8ed456.jpg b/data/thumb-cache/e3d05b503f89a0a1ff8ed456.jpg
new file mode 100644
index 0000000..a4072b2
Binary files /dev/null and b/data/thumb-cache/e3d05b503f89a0a1ff8ed456.jpg differ
diff --git a/data/thumb-cache/e934fd973f3fbcc4acc0f809.jpg b/data/thumb-cache/e934fd973f3fbcc4acc0f809.jpg
new file mode 100644
index 0000000..55fd8cb
Binary files /dev/null and b/data/thumb-cache/e934fd973f3fbcc4acc0f809.jpg differ
diff --git a/data/thumb-cache/eb550c8e11ad1aa92c6c6c79.jpg b/data/thumb-cache/eb550c8e11ad1aa92c6c6c79.jpg
new file mode 100644
index 0000000..c759c53
Binary files /dev/null and b/data/thumb-cache/eb550c8e11ad1aa92c6c6c79.jpg differ
diff --git a/data/thumb-cache/f551b80de266aad6e43aead7.jpg b/data/thumb-cache/f551b80de266aad6e43aead7.jpg
new file mode 100644
index 0000000..ccbc225
Binary files /dev/null and b/data/thumb-cache/f551b80de266aad6e43aead7.jpg differ
diff --git a/public/js/showroom.js b/public/js/showroom.js
index 13cb69b..6aa41db 100644
--- a/public/js/showroom.js
+++ b/public/js/showroom.js
@@ -1554,21 +1554,28 @@ function loadWingBook(pivot, onDone) {
const sliverTexCache = {};
let _sliverInFlight = 0;
const SLIVER_MAX = 3; // concurrent thumbnail fetches (budget-safe)
-const SLIVER_THUMB_PX = 120; // downscaled width for remote Shopify images
+const SLIVER_THUMB_PX = 160; // downscaled width — 160 keeps a steeply-raked sliver legible (Contrarian: 120 squeezed to ~3px = mush)
let _sliverPumpAt = 0;
const SLIVER_PUMP_MS = 90; // min gap between kicking off new thumbnail loads
-// Build the low-res source URL for a board's pattern. Remote Shopify images get a
-// width param so the CDN downscales server-side; local /gen-tiles are already small.
-function sliverThumbSrc(imageUrl) {
+// Build the LOW-RES source URL for a closed board's sliver. Routes through the server's
+// /api/thumb downscaler (sharp, disk-cached) so the texture budget stays tiny:
+// • local gen-tiles (which are 2000²+ 12 MB PNGs!) → downscale by SKU, NEVER served raw
+// • remote heroes → downscale the whitelisted URL
+// Falls back to the raw proxy only if neither a SKU nor a remote URL is available.
+function sliverThumbSrc(product, imageUrl) {
+ const sku = product && (product.sku || product.mfr_sku);
+ // Prefer the SKU path: it downscales the crisp local gen-tile (and dodges a 12 MB PNG).
+ if (sku && imageUrl && imageUrl.charAt(0) === '/' && imageUrl.indexOf('/gen-tiles/') !== -1) {
+ return '/api/thumb?sku=' + encodeURIComponent(sku) + '&w=' + SLIVER_THUMB_PX;
+ }
if (!imageUrl) return null;
- if (imageUrl.charAt(0) === '/') return imageUrl; // local tile/asset — already small
- // Append Shopify's width= param INSIDE the proxied URL so the CDN returns a tiny JPEG.
- let thumbUrl = imageUrl;
- if (imageUrl.indexOf('cdn.shopify.com') !== -1) {
- thumbUrl += (imageUrl.indexOf('?') === -1 ? '?' : '&') + 'width=' + SLIVER_THUMB_PX;
+ if (imageUrl.charAt(0) === '/') {
+ // Local non-tile asset (already small) — serve as-is.
+ return imageUrl;
}
- return '/api/proxy/image?url=' + encodeURIComponent(thumbUrl);
+ // Remote: downscale via /api/thumb (sharp) rather than shipping the full 125 KB hero.
+ return '/api/thumb?url=' + encodeURIComponent(imageUrl) + '&w=' + SLIVER_THUMB_PX;
}
// Apply a (real, low-res) thumbnail texture to a CLOSED board's face. Uses a cheap
@@ -1610,7 +1617,8 @@ function loadSliverThumb(pivot, onDone) {
apply(cached);
};
- const src = sliverThumbSrc(imageUrl);
+ const src = sliverThumbSrc(product, imageUrl);
+ if (!src) { if (onDone) onDone(); return; }
if (typeof createImageBitmap === 'function' && src.charAt(0) === '/') {
fetch(src).then(r => r.blob()).then(b => createImageBitmap(b))
.then(bmp => buildFrom(bmp))
diff --git a/server.js b/server.js
index e1c20f4..2df030f 100644
--- a/server.js
+++ b/server.js
@@ -145,6 +145,81 @@ app.get('/api/proxy/image', (req, res) => {
}
});
+// ============================================================
+// SLIVER THUMBNAIL — downscaled real-design strips for the CLOSED wingboards (V1).
+// The PJ photo shows a thin sliver of EVERY real design in the packed arc. Painting
+// the full assets onto closed boards is wasteful (local gen-tiles are 2000²+ 12 MB
+// PNGs; remote heroes are 125 KB). This serves a tiny JPEG (default 128 px wide) of any
+// allowed source, downscaled with sharp and disk-cached, so 24 closed slivers cost a
+// few KB each instead of multiple MB. Used ONLY for closed slivers; the open hero still
+// loads the full asset via /gen-tiles or the proxy.
+// ?sku=<DW SKU> → downscale the local gen-tile for that SKU (preferred, crisp + local)
+// ?url=<https…> → downscale a whitelisted remote image
+// ?w=<px> → target width (clamped 48..256, default 128)
+// ============================================================
+let sharp = null;
+try { sharp = require('sharp'); } catch (e) { console.warn('[thumb] sharp not available — sliver thumbs fall back to proxy'); }
+const THUMB_CACHE = path.join(DATA_DIR, 'thumb-cache');
+try { fs.mkdirSync(THUMB_CACHE, { recursive: true }); } catch (e) {}
+
+function sendThumb(res, buf, key) {
+ res.setHeader('Content-Type', 'image/jpeg');
+ res.setHeader('Cache-Control', 'public, max-age=604800');
+ res.end(buf);
+}
+
+app.get('/api/thumb', async (req, res) => {
+ if (!sharp) {
+ // FAIL-SAFE (not fail-heavy): without sharp we can't downscale; redirecting to the full
+ // 125KB proxy or — worse — the 12MB gen-tile PNG would invert this optimization into an
+ // FPS disaster on the rack. 503 → the client keeps the cheap synthetic-pool sliver and
+ // logs, rather than shovelling heavy assets at the GPU. (Contrarian 2026-06-28)
+ return res.status(503).send('thumb unavailable (no sharp); client uses pool fallback');
+ }
+ const w = Math.max(48, Math.min(256, parseInt(req.query.w) || 128));
+ const sku = (req.query.sku || '').replace(/[^A-Za-z0-9_-]/g, '');
+ const url = req.query.url;
+
+ // Cache key by source + width
+ const crypto = require('crypto');
+ const ck = crypto.createHash('sha1').update((sku || url || '') + '|' + w).digest('hex').slice(0, 24);
+ const cacheFile = path.join(THUMB_CACHE, ck + '.jpg');
+ try {
+ if (fs.existsSync(cacheFile)) return sendThumb(res, fs.readFileSync(cacheFile));
+ } catch (e) {}
+
+ const downscale = async (inputBuf) => {
+ const out = await sharp(inputBuf).resize({ width: w, withoutEnlargement: true })
+ .jpeg({ quality: 72 }).toBuffer();
+ try { fs.writeFileSync(cacheFile, out); } catch (e) {}
+ return out;
+ };
+
+ try {
+ if (sku) {
+ const tile = path.join(DATA_DIR, 'gen-tiles', sku + '.png');
+ if (!fs.existsSync(tile)) return res.status(404).send('No tile');
+ return sendThumb(res, await downscale(fs.readFileSync(tile)));
+ }
+ if (url) {
+ let parsed;
+ try { parsed = new URL(url); } catch { return res.status(400).send('Bad url'); }
+ if (parsed.protocol !== 'https:' || !ALLOWED_HOSTS.has(parsed.hostname)) return res.status(403).send('Host not allowed');
+ const https = require('https');
+ const buf = await new Promise((resolve, reject) => {
+ https.get(url, (pr) => {
+ if (pr.statusCode >= 400) { reject(new Error('status ' + pr.statusCode)); pr.resume(); return; }
+ const chunks = []; pr.on('data', c => chunks.push(c)); pr.on('end', () => resolve(Buffer.concat(chunks)));
+ }).on('error', reject);
+ });
+ return sendThumb(res, await downscale(buf));
+ }
+ return res.status(400).send('Missing source');
+ } catch (e) {
+ return res.status(502).send('Thumb error: ' + e.message);
+ }
+});
+
app.listen(PORT, '0.0.0.0', () => {
console.log(`Quadrille House Wallcovering Showroom on http://0.0.0.0:${PORT} (${PRODUCTS.length} wings)`);
});
← 765e004 Proto V6-V10: refresh final verification screenshots (0 cons
·
back to Quadrille Showroom
·
Wire Sample Table into the version picker as V11 (Add Sample d9c5d8c →