← back to Rentv 2026
News map: collapse nav into a hamburger + log all articles in sitemap
5c689bb610221f5b283ac35d817122b542fb1fbb · 2026-08-06 09:51:25 -0700 · Steve Abrams
- Map chrome was eating 310px (393 on mobile) before the map. Hide the injected
region/section tab strip and move ALL nav into a hamburger drawer (upper-right);
collapse the filter controls to one compact scrollable row; hide util bar + legend
on mobile. Map now starts at ~150px desktop / ~138px mobile.
- sitemap.xml: log EVERY RENTV article (full corpus, ~4,466) individually, not just
the 30 recent — deduped corpus + live-feed.
TK-10284
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
M public/map.htmlM server.js
Diff
commit 5c689bb610221f5b283ac35d817122b542fb1fbb
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Thu Aug 6 09:51:25 2026 -0700
News map: collapse nav into a hamburger + log all articles in sitemap
- Map chrome was eating 310px (393 on mobile) before the map. Hide the injected
region/section tab strip and move ALL nav into a hamburger drawer (upper-right);
collapse the filter controls to one compact scrollable row; hide util bar + legend
on mobile. Map now starts at ~150px desktop / ~138px mobile.
- sitemap.xml: log EVERY RENTV article (full corpus, ~4,466) individually, not just
the 30 recent — deduped corpus + live-feed.
TK-10284
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
public/map.html | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--
server.js | 8 ++++++--
2 files changed, 67 insertions(+), 4 deletions(-)
diff --git a/public/map.html b/public/map.html
index 8f914e1b..b7761419 100644
--- a/public/map.html
+++ b/public/map.html
@@ -78,10 +78,52 @@ aside .ah{padding:12px 16px;border-bottom:1px solid var(--line);font-size:12px;f
.cl.g{background:rgba(26,158,75,.9)}.cl.r{background:rgba(200,16,46,.88)}
.me{background:#1467d6;border:3px solid #fff;border-radius:50%;width:18px;height:18px;box-shadow:0 0 0 4px rgba(20,103,214,.3)}
@media(max-width:760px){aside{position:absolute;right:0;top:auto;bottom:0;height:44%;width:100%;flex-basis:auto;border-left:0;border-top:1px solid var(--line);z-index:1000}
- .stage{position:relative}.bar h1{font-size:16px}}
+ .stage{position:relative}.bar h1{font-size:15px}}
+/* ── Hamburger + drawer: all the nav tabs collapse in here so the map gets the screen ── */
+.rentvtabs{display:none!important} /* injected region/section strip → moved into the drawer */
+.mast{position:relative;display:flex;align-items:center;justify-content:center;padding:10px 54px}
+.ham{position:absolute;right:14px;top:50%;transform:translateY(-50%);background:#fff;border:1.5px solid var(--line);border-radius:9px;font-size:17px;line-height:1;padding:8px 11px;cursor:pointer;color:var(--ink)}
+.ham:hover{border-color:var(--red);color:var(--red)}
+.drawer{position:fixed;inset:0;z-index:4000;display:none}
+.drawer.open{display:block}
+.drawer .bd{position:absolute;inset:0;background:rgba(0,0,0,.45)}
+.drawer .pl{position:absolute;top:0;right:0;width:min(88vw,320px);height:100%;background:#fff;overflow:auto;padding:18px 16px 44px;box-shadow:-10px 0 44px rgba(0,0,0,.32)}
+.drawer .pl h3{font-family:'Playfair Display',serif;font-size:19px;margin:0 0 2px}
+.drawer .x{position:absolute;top:12px;right:14px;font-size:24px;background:none;border:0;cursor:pointer;color:var(--sub);line-height:1}
+.drawer .gt{font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:.08em;color:var(--sub);margin:18px 0 5px}
+.drawer a{display:block;padding:9px 4px;border-bottom:1px solid var(--line);color:var(--ink);font-weight:600;font-size:14.5px;white-space:normal}
+.drawer a:hover{color:var(--red)}
+.drawer .clone{display:flex;flex-wrap:wrap;gap:2px 4px}
+.drawer .clone a{border:0;display:inline-block;padding:5px 8px;font-size:12.5px;background:var(--wash);border-radius:6px;font-weight:600}
+.drawer .clone .rt-k,.drawer .clone .rt-div{display:none}
+/* compact single-row filter bar (scrolls sideways instead of stacking) */
+.bar .wrap{flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch;gap:10px 14px}
+.bar .wrap::-webkit-scrollbar{display:none}
+.bar h1{flex:0 0 auto}
+@media(max-width:760px){.legend{display:none}.mast{padding:8px 50px}.mast .logo{font-size:24px}.util{display:none}}
</style></head><body>
<div class="util"><div class="wrap"><a href="/">RENTV.com · Commercial Real Estate News</a><a href="/">← Front page</a></div></div>
-<header class="mast"><a class="logo" href="/">REN<span>TV</span>.com<small>News Map</small></a></header>
+<header class="mast"><a class="logo" href="/">REN<span>TV</span>.com<small>News Map</small></a><button class="ham" id="ham" aria-label="Open menu" aria-expanded="false">☰</button></header>
+<div class="drawer" id="drawer" aria-hidden="true">
+ <div class="bd" id="drawerBd"></div>
+ <div class="pl">
+ <button class="x" id="drawerX" aria-label="Close menu">×</button>
+ <h3>REN<span style="color:var(--red)">TV</span>.com</h3>
+ <div class="gt">Explore</div>
+ <a href="/">Front page</a>
+ <a href="/map">🗺 News Map</a>
+ <a href="/markets">Markets</a>
+ <a href="/review">The REview</a>
+ <a href="/cre-talk">CRE Talk</a>
+ <a href="/conferences">Conferences</a>
+ <a href="/blog">Blog</a>
+ <a href="/about">About</a>
+ <a href="/advertise">Advertise</a>
+ <a href="/subscribe">Subscribe</a>
+ <div class="gt">Regions & Sections</div>
+ <div id="drawerNav"></div>
+ </div>
+</div>
<div class="bar"><div class="wrap">
<h1>News Around You <span class="n" id="cnt"></span></h1>
<span class="legend"><span><span class="dot g"></span>Last 3 months</span><span><span class="dot r"></span>Older</span></span>
@@ -118,6 +160,23 @@ aside .ah{padding:12px 16px;border-bottom:1px solid var(--line);font-size:12px;f
var esc=function(s){return (s||'').replace(/[&<>"]/g,function(c){return {'&':'&','<':'<','>':'>','"':'"'}[c];});};
var $=function(id){return document.getElementById(id);};
+// Hamburger drawer — houses ALL nav tabs (the injected region/section strip is hidden and
+// cloned in here) so the map keeps the screen.
+function openDrawer(){
+ var host=$('drawerNav');
+ if(!host.getAttribute('data-filled')){
+ var t=document.querySelector('.rentvtabs');
+ host.innerHTML = t ? '<div class="clone">'+t.innerHTML+'</div>' : '<div style="color:var(--sub);font-size:13px">Loading…</div>';
+ if(t) host.setAttribute('data-filled','1'); // retry next open until the injected nav exists
+ }
+ var d=$('drawer'); d.classList.add('open'); d.setAttribute('aria-hidden','false'); $('ham').setAttribute('aria-expanded','true');
+}
+function closeDrawer(){ var d=$('drawer'); d.classList.remove('open'); d.setAttribute('aria-hidden','true'); $('ham').setAttribute('aria-expanded','false'); }
+$('ham').onclick=openDrawer; $('drawerX').onclick=closeDrawer; $('drawerBd').onclick=closeDrawer;
+document.addEventListener('keydown',function(e){if(e.key==='Escape')closeDrawer();});
+// close after tapping a link inside the drawer
+$('drawer').addEventListener('click',function(e){ if(e.target.closest('a')) closeDrawer(); });
+
// "Last 3 months" is computed HERE, at load, so freshness is always relative to today.
var CUTOFF=(function(){var d=new Date();d.setMonth(d.getMonth()-3);return d;})();
function isFresh(a){ return a.date && new Date(a.date+'T00:00:00') >= CUTOFF; }
diff --git a/server.js b/server.js
index 5c9b49ca..dad4a748 100644
--- a/server.js
+++ b/server.js
@@ -1371,8 +1371,12 @@ app.get('/sitemap.xml', (req, r) => {
const urls = ['/', '/map', '/markets', '/review', '/topics', '/blog'];
(readHubs().hubs || []).forEach(h => { if (hubMatches(h, items).length > 0) urls.push('/topic/' + h.slug); });
(readRegions().regions || []).forEach(reg => { if (regionMatches(reg, items).length > 0) urls.push('/region/' + reg.slug); });
- // Article-level entries for the live news feed so stories are individually indexable.
- (Array.isArray(items) ? items : []).forEach(it => { if (it && it.id) urls.push('/news/' + it.id); });
+ // Article-level entries for EVERY logged RENTV story — the full corpus plus any live-feed
+ // items not yet in it — so all articles by RENTV are individually indexable (deduped).
+ const seenIds = new Set();
+ const addArticle = (a) => { const id = a && a.id; if (id && !seenIds.has(id)) { seenIds.add(id); urls.push('/news/' + id); } };
+ try { corpus().forEach(addArticle); } catch {}
+ (Array.isArray(items) ? items : []).forEach(addArticle);
const body = urls.map(u => ` <url><loc>${base}${u}</loc></url>`).join('\n');
r.type('application/xml').send(`<?xml version="1.0" encoding="UTF-8"?>\n<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n${body}\n</urlset>\n`);
});
← 89d927a8 chore: bump version to 0.21.1 (session close — cycles 16-40
·
back to Rentv 2026
·
auto-save: 2026-08-06T09:51:16 (8 files) — data/deals-regist cb99f313 →