← 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
M public/2026/a.htmlM public/2026/b.htmlM public/2026/c.htmlM public/2026/d.htmlM public/2026/e.htmlM public/advertise.htmlM public/index.htmlA public/template-toggle.js
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 →