← back to Rentv
index: honor ?cat= so each hamburger section shows its own filtered feed
214915365f26811d2941dc502a62ec4c1fed9135 · 2026-07-23 14:06:12 -0700 · Steve Abrams
Section links (/sales,/development,…) 301 to /?cat=X but index.html ignored
the param and rendered the identical homepage — every hamburger link showed the
same info. Now the client filters the live feed to the active category, shows a
section masthead with story count + All-news escape, highlights the active drawer
link, sets the title, and handles the empty-section case.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
Diff
commit 214915365f26811d2941dc502a62ec4c1fed9135
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Thu Jul 23 14:06:12 2026 -0700
index: honor ?cat= so each hamburger section shows its own filtered feed
Section links (/sales,/development,…) 301 to /?cat=X but index.html ignored
the param and rendered the identical homepage — every hamburger link showed the
same info. Now the client filters the live feed to the active category, shows a
section masthead with story count + All-news escape, highlights the active drawer
link, sets the title, and handles the empty-section case.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
public/index.html | 46 +++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 41 insertions(+), 5 deletions(-)
diff --git a/public/index.html b/public/index.html
index 5cffc7a5..e6242a4a 100644
--- a/public/index.html
+++ b/public/index.html
@@ -29,6 +29,16 @@
.grp{padding:14px 18px 4px}.grp .gt{font-size:10px;letter-spacing:.16em;text-transform:uppercase;color:#6b747d;margin-bottom:6px}
.drawer nav a{display:block;padding:9px 18px;color:#dbe1e7;font-size:14.5px;border-left:3px solid transparent}
.drawer nav a:hover{background:#141a21;border-left-color:var(--red);color:#fff}
+ .drawer nav a.active{background:#141a21;border-left-color:var(--red);color:#fff;font-weight:700}
+ .sechat{display:none;align-items:baseline;gap:14px;flex-wrap:wrap;padding:20px 0 4px;border-bottom:1px solid #e8e4e0;margin-bottom:4px}
+ .sechat.on{display:flex}
+ .sechat h1{font-family:'Playfair Display',serif;font-size:clamp(30px,3vw,42px);font-weight:700;letter-spacing:-.01em}
+ .sechat .ct{color:var(--sub);font-size:13px;font-weight:600}
+ .sechat .all{margin-left:auto;color:var(--red);font-weight:800;font-size:12px;letter-spacing:.06em;text-transform:uppercase}
+ .sechat .all:hover{text-decoration:underline}
+ .empty{padding:60px 0 40px;text-align:center;color:var(--sub)}
+ .empty h3{font-family:'Playfair Display',serif;font-size:26px;color:var(--ink);margin-bottom:8px}
+ .empty a{color:var(--red);font-weight:800}
.drawer .df{margin-top:auto;padding:16px 18px;border-top:1px solid #1c232b;font-size:11px;color:#6b747d}
.datastrip{border-bottom:1px solid #e8e4e0;background:#f7f5f2}
.datastrip .in{max-width:1240px;margin:0 auto;display:flex;gap:34px;padding:9px 22px;font-size:11px;font-weight:500;letter-spacing:.06em;color:#4a4f55;overflow:hidden;white-space:nowrap}
@@ -104,7 +114,7 @@
<div class="fold">
<div class="datastrip"><div class="in" id="datastrip"></div></div>
- <main class="wrap"><section class="hero"><div class="lead" id="lead"></div><div class="aside" id="aside"></div></section></main>
+ <main class="wrap"><div class="sechat" id="sechat"></div><section class="hero"><div class="lead" id="lead"></div><div class="aside" id="aside"></div></section></main>
<div class="selbar" id="selbar"></div>
<div class="breaking"><div class="in"><div class="lbl"><span class="dot"></span> Breaking</div>
<div class="ticker" id="ticker"><div class="fade l"></div><div class="fade r"></div><span class="paused">Paused · hover to browse</span><div class="track" id="track"></div></div></div></div>
@@ -130,19 +140,45 @@ $('dclose').onclick=closeDrawer;$('scrim').onclick=closeDrawer;
$('user').onclick=()=>location.href='/subscribe';
async function jget(url){try{const r=await fetch(url,{credentials:'same-origin'});if(!r.ok)return null;return await r.json();}catch(e){return null;}}
let ALL=[];
+// Canonical section labels — the drawer/footer link to /sales, /development, … which the
+// server 301s to /?cat=Sales, /?cat=Development, … Match the exact cat tags in the live feed.
+const SECTIONS={sales:'Sales',leases:'Leases',financing:'Financing',development:'Development',multifamily:'Multifamily',industrial:'Industrial',retail:'Retail'};
+const rawCat=(new URLSearchParams(location.search).get('cat')||'').trim();
+const CAT=rawCat?(SECTIONS[rawCat.toLowerCase()]||rawCat):''; // canonical label, or '' for the full homepage
+if(CAT){
+ document.title=CAT+' — RENTV.com Commercial Real Estate News';
+ // Highlight the matching section in the drawer so the open section is obvious.
+ document.querySelectorAll('.drawer nav a').forEach(a=>{
+ if((a.getAttribute('href')||'').toLowerCase()==='/'+CAT.toLowerCase()) a.classList.add('active');
+ });
+}
async function load(){
const [d,pd]=await Promise.all([jget('/api/news'),jget('/api/posts?status=published')]);
const news=(d&&d.items)||[], orig=((pd&&pd.items)||[]).map(p=>({id:p.id,title:p.title,cat:p.cat,image:p.image,author:p.author,orig:true}));
ALL=orig.concat(news);
- if(!ALL.length){$('lead').innerHTML='<div class="tag">RENTV.com</div><h1>Live commercial real estate news, refreshing…</h1><div class="byl">If this persists, the wire is briefly unavailable — please reload.</div>';return;}
+ // A "section" IS the live feed filtered to one category (server-side model in server.js). When
+ // ?cat= is set we render only that slice — that's what makes each hamburger link show DIFFERENT info.
+ const view=CAT?ALL.filter(x=>x&&String(x.cat||'').toLowerCase()===CAT.toLowerCase()):ALL;
+ const sh=$('sechat');
+ if(CAT&&sh){
+ sh.innerHTML=`<h1>${esc(CAT)}</h1><span class="ct">${view.length} ${view.length===1?'story':'stories'}</span><a class="all" href="/">All news ↗</a>`;
+ sh.classList.add('on');
+ }
+ if(!view.length){
+ // Either the wire is empty (homepage) or this section has no current stories.
+ $('lead').innerHTML='';$('aside').innerHTML='';$('river').innerHTML='';$('track').innerHTML='';
+ if(CAT){$('lead').innerHTML=`<div class="empty"><h3>No current ${esc(CAT)} stories</h3><div>This section refreshes from the live wire. <a href="/">Browse all news →</a></div></div>`;}
+ else{$('lead').innerHTML='<div class="tag">RENTV.com</div><h1>Live commercial real estate news, refreshing…</h1><div class="byl">If this persists, the wire is briefly unavailable — please reload.</div>';}
+ return;
+ }
// lead with the top story that HAS an image (never a blank-image placeholder); keep the rest in order
- const li=ALL.findIndex(x=>x&&x.image); const lead=li>=0?ALL[li]:ALL[0];
- const rest=ALL.filter((_,i)=>i!==(li>=0?li:0));
+ const li=view.findIndex(x=>x&&x.image); const lead=li>=0?view[li]:view[0];
+ const rest=view.filter((_,i)=>i!==(li>=0?li:0));
const l=lead;
$('lead').innerHTML=`<div class="im"${bg(l)}></div><span class="tag">${esc(l.cat||'RENTV')}${l.orig?'<span class="chipo">Original</span>':''}</span><h1>${esc(l.title)}</h1><div class="byl">${l.orig?'By '+esc(l.author||'RENTV Staff')+' · RENTV Original':'By RENTV Staff · live from rentv.com'}</div>`;
$('lead').style.cursor='pointer';$('lead').onclick=()=>location.href=LK(l);
$('aside').innerHTML=rest.slice(0,4).map(n=>`<a href="${LK(n)}"><div class="im"${bg(n)}></div><div><span class="tag" style="color:var(--red)">${esc(n.cat||'')}</span><h4>${esc(n.title)}</h4></div></a>`).join('');
- const items=ALL.slice(0,16), mk=n=>`<a class="it" data-id="${esc(n.id)}" data-cat="${esc(n.cat||'')}" data-title="${esc(n.title)}" data-href="${LK(n)}"><span class="c">${esc(n.cat||'')}</span>${esc(n.title)}</a>`;
+ const items=view.slice(0,16), mk=n=>`<a class="it" data-id="${esc(n.id)}" data-cat="${esc(n.cat||'')}" data-title="${esc(n.title)}" data-href="${LK(n)}"><span class="c">${esc(n.cat||'')}</span>${esc(n.title)}</a>`;
$('track').innerHTML=items.map(mk).join('')+items.map(mk).join('');
const selbar=$('selbar');
$('track').querySelectorAll('.it').forEach(a=>a.addEventListener('click',e=>{e.preventDefault();
← 65b2eece auto-save: 2026-07-23T13:51:43 (3 files) — data/markets.json
·
back to Rentv
·
Localize all rentv.com photos + drop link-outs (serve everyt f934418a →