[object Object]

← back to Rentv 2026

rentv 2026: admin front-end template toggle

e6e748c4aba5914f576e49d5ef9d344689d3c82f · 2026-08-07 13:44:40 -0700 · Steve (RENTV 2026)

Floating switcher (public/template-toggle.js) lets a logged-in admin/user flip the
live front end between the original site + the 5 concepts (A-E) from the front end.
Gating: live front page shows it only for an authed admin/user session (/api/whoami);
concept pages (/2026/*, /advertise) always show it (demoable); ?tt=1 forces it on.
Marks the chosen site with a ★ (reads site-template.json). Injected into index +
all 5 templates + advertise.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit e6e748c4aba5914f576e49d5ef9d344689d3c82f
Author: Steve (RENTV 2026) <steve@designerwallcoverings.com>
Date:   Fri Aug 7 13:44:40 2026 -0700

    rentv 2026: admin front-end template toggle
    
    Floating switcher (public/template-toggle.js) lets a logged-in admin/user flip the
    live front end between the original site + the 5 concepts (A-E) from the front end.
    Gating: live front page shows it only for an authed admin/user session (/api/whoami);
    concept pages (/2026/*, /advertise) always show it (demoable); ?tt=1 forces it on.
    Marks the chosen site with a ★ (reads site-template.json). Injected into index +
    all 5 templates + advertise.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 public/2026/a.html        |  1 +
 public/2026/b.html        |  1 +
 public/2026/c.html        |  1 +
 public/2026/d.html        |  1 +
 public/2026/e.html        |  1 +
 public/advertise.html     |  1 +
 public/index.html         |  1 +
 public/template-toggle.js | 94 +++++++++++++++++++++++++++++++++++++++++++++++
 8 files changed, 101 insertions(+)

diff --git a/public/2026/a.html b/public/2026/a.html
index 2e02b257..0c4bb63d 100644
--- a/public/2026/a.html
+++ b/public/2026/a.html
@@ -1347,5 +1347,6 @@ img { display: block; }
 })();
 </script>
 <script src="/2026/elements.js" defer></script>
+<script src="/template-toggle.js" defer></script>
 </body>
 </html>
diff --git a/public/2026/b.html b/public/2026/b.html
index 91198194..f32cc936 100644
--- a/public/2026/b.html
+++ b/public/2026/b.html
@@ -1468,5 +1468,6 @@ button { cursor: pointer; border: none; background: none; font: inherit; }
 })();
 </script>
 <script src="/2026/elements.js" defer></script>
+<script src="/template-toggle.js" defer></script>
 </body>
 </html>
diff --git a/public/2026/c.html b/public/2026/c.html
index efe26532..ba053bc8 100644
--- a/public/2026/c.html
+++ b/public/2026/c.html
@@ -1091,5 +1091,6 @@ init();
 })();
 </script>
 <script src="/2026/elements.js" defer></script>
+<script src="/template-toggle.js" defer></script>
 </body>
 </html>
diff --git a/public/2026/d.html b/public/2026/d.html
index d109ba2f..8dd90156 100644
--- a/public/2026/d.html
+++ b/public/2026/d.html
@@ -1710,5 +1710,6 @@ loadOriginals();
 </script>
 
 <script src="/2026/elements.js" defer></script>
+<script src="/template-toggle.js" defer></script>
 </body>
 </html>
diff --git a/public/2026/e.html b/public/2026/e.html
index 4c0cca3d..af5bbd40 100644
--- a/public/2026/e.html
+++ b/public/2026/e.html
@@ -1407,5 +1407,6 @@ footer {
 })();
 </script>
 <script src="/2026/elements.js" defer></script>
+<script src="/template-toggle.js" defer></script>
 </body>
 </html>
diff --git a/public/advertise.html b/public/advertise.html
index 117b76c1..31748acd 100644
--- a/public/advertise.html
+++ b/public/advertise.html
@@ -310,4 +310,5 @@ $('#rForm').addEventListener('submit',async e=>{e.preventDefault();
 loadPersist(); loadRate(); loadInv();
 </script>
 <script src="/2026/elements.js" defer></script>
+<script src="/template-toggle.js" defer></script>
 </body></html>
diff --git a/public/index.html b/public/index.html
index bff6e598..9ef4f329 100644
--- a/public/index.html
+++ b/public/index.html
@@ -387,4 +387,5 @@ async function loadFeaturedVideo(){
 }
 load(); setInterval(load,120000); loadTicker(); setInterval(loadTicker,120000); loadPulseEmbed(); setInterval(loadPulseEmbed,120000); loadFeaturedVideo();
 </script>
+<script src="/template-toggle.js" defer></script>
 </body></html>
diff --git a/public/template-toggle.js b/public/template-toggle.js
new file mode 100644
index 00000000..361bca04
--- /dev/null
+++ b/public/template-toggle.js
@@ -0,0 +1,94 @@
+/* RENTV — admin front-end TEMPLATE TOGGLE (drop-in).
+ *
+ * A floating switcher that lets a logged-in ADMIN/USER flip the live front end
+ * between the original site and the 5 2026 concepts, from the front end itself.
+ *
+ * Include on any page:  <script src="/template-toggle.js" defer></script>
+ *
+ * Visibility:
+ *   • On the live front page / storefront → shows ONLY for an authenticated
+ *     admin or user session (GET /api/whoami role). Public visitors never see it.
+ *   • On the /2026/* concept pages and /advertise → always shown (internal
+ *     preview surfaces), so it's demoable even in the open preview.
+ *   • Force on anywhere with ?tt=1 (or localStorage rentv_tt='1').
+ *
+ * The ★ marks the currently-chosen site (data/site-template.json via the
+ * /api/ad/ad-system module) so the room can see which one is "the pick".
+ */
+(function () {
+  var TPL = [
+    { k: 'orig', name: 'Original', url: '/' },
+    { k: 'a', name: 'A · Video Wall', url: '/2026/a.html' },
+    { k: 'b', name: 'B · Editorial', url: '/2026/b.html' },
+    { k: 'c', name: 'C · Cinematic', url: '/2026/c.html' },
+    { k: 'd', name: 'D · Magazine', url: '/2026/d.html' },
+    { k: 'e', name: 'E · Dashboard', url: '/2026/e.html' }
+  ];
+  var path = location.pathname;
+  var FORCE = /\/2026\//.test(path) || /advertise/.test(path) ||
+    /[?&]tt=1/.test(location.search) || (function () { try { return localStorage.getItem('rentv_tt') === '1'; } catch (e) { return false; } })();
+
+  function currentKey() {
+    var m = path.match(/2026\/([a-e])\.html/); if (m) return m[1];
+    if (path === '/' || path === '/index.html') return 'orig';
+    return null; // e.g. /advertise — nothing highlighted
+  }
+
+  function css() {
+    if (document.getElementById('rentv-tt-css')) return;
+    var s = document.createElement('style'); s.id = 'rentv-tt-css';
+    s.textContent = [
+      '#rentv-tt{position:fixed;right:14px;bottom:14px;z-index:2147483400;font:700 12px Inter,system-ui,sans-serif}',
+      '#rentv-tt .pill{display:flex;align-items:center;gap:8px;background:#0b0e12;color:#e7ecf1;border:1px solid #c8102e;',
+      '  border-radius:11px;padding:8px 12px;box-shadow:0 10px 30px rgba(0,0,0,.45);cursor:pointer;user-select:none}',
+      '#rentv-tt .pill .dot{width:8px;height:8px;border-radius:50%;background:#c8102e}',
+      '#rentv-tt .pill .cur{color:#fff}',
+      '#rentv-tt .pill .cx{color:#8b949e;font-weight:800;margin-left:2px}',
+      '#rentv-tt .menu{position:absolute;right:0;bottom:44px;background:#0b0e12;border:1px solid #1c232b;border-radius:11px;',
+      '  overflow:hidden;min-width:190px;box-shadow:0 18px 50px rgba(0,0,0,.5);display:none}',
+      '#rentv-tt.open .menu{display:block}',
+      '#rentv-tt .menu .hd{padding:9px 13px;border-bottom:1px solid #1c232b;color:#7b848d;font:800 10px Inter;letter-spacing:.14em;text-transform:uppercase}',
+      '#rentv-tt .menu a{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:10px 13px;color:#dbe1e7;',
+      '  border-left:3px solid transparent;text-decoration:none}',
+      '#rentv-tt .menu a:hover{background:#141a21;border-left-color:#c8102e;color:#fff}',
+      '#rentv-tt .menu a.on{background:#141a21;border-left-color:#c8102e;color:#fff}',
+      '#rentv-tt .menu a .star{color:#c6a24a}',
+      '#rentv-tt .menu .ft{padding:8px 13px;border-top:1px solid #1c232b;color:#6b747d;font:600 10px Inter}'
+    ].join('');
+    document.head.appendChild(s);
+  }
+
+  function render(chosen) {
+    css();
+    var cur = currentKey();
+    var curName = (TPL.find(function (t) { return t.k === cur; }) || {}).name || 'This page';
+    var wrap = document.createElement('div'); wrap.id = 'rentv-tt';
+    wrap.innerHTML =
+      '<div class="menu"><div class="hd">Switch front-end template</div>' +
+      TPL.map(function (t) {
+        return '<a href="' + t.url + '" class="' + (t.k === cur ? 'on' : '') + '">' +
+          '<span>' + t.name + '</span>' + (t.k === chosen ? '<span class="star">★ chosen</span>' : '') + '</a>';
+      }).join('') +
+      '<div class="ft">Admin-only · live template switch</div></div>' +
+      '<div class="pill"><span class="dot"></span><span class="cur">' + curName + '</span><span class="cx">▾ Templates</span></div>';
+    document.body.appendChild(wrap);
+    wrap.querySelector('.pill').addEventListener('click', function () { wrap.classList.toggle('open'); });
+    document.addEventListener('click', function (e) { if (!wrap.contains(e.target)) wrap.classList.remove('open'); });
+  }
+
+  function boot() {
+    // fetch chosen-template marker (best-effort) + whoami for gating
+    var chosen = null;
+    fetch('/api/ad/site-template', { credentials: 'same-origin' }).then(function (r) { return r.ok ? r.json() : null; })
+      .then(function (j) { if (j && j.chosen) chosen = j.chosen; })
+      .catch(function () { })
+      .then(function () {
+        if (FORCE) return render(chosen);
+        // otherwise only for an authenticated admin/user session
+        fetch('/api/whoami', { credentials: 'same-origin' }).then(function (r) { return r.ok ? r.json() : null; })
+          .then(function (w) { if (w && w.authed && (w.role === 'admin' || w.role === 'user')) render(chosen); })
+          .catch(function () { });
+      });
+  }
+  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', boot); else boot();
+})();

← 23094df1 rentv: re-gate site behind un/pw (reverse 2026-08-06 public  ·  back to Rentv 2026  ·  template-toggle: add admin 'View all — compare' overlay (all 3e325c5f →