← back to Rentv V1
rentv.com full-site rebuild: article reader-proxy (live story+photo+body in our shell), /api/markets route, company pages (conferences/advertise/subscribe/about) via build.mjs, wired all dead nav/footer links, OPEN local-preview bypass
5e58ee5cc4b847a052e42f8472e68602b3989fb0 · 2026-07-21 12:58:22 -0700 · Steve Abrams
Files touched
A build.mjsM data/markets.jsonM data/news.jsonM data/ticker.jsonA public/about.htmlA public/advertise.htmlA public/conferences.htmlM public/index.htmlA public/subscribe.htmlM server.js
Diff
commit 5e58ee5cc4b847a052e42f8472e68602b3989fb0
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Tue Jul 21 12:58:22 2026 -0700
rentv.com full-site rebuild: article reader-proxy (live story+photo+body in our shell), /api/markets route, company pages (conferences/advertise/subscribe/about) via build.mjs, wired all dead nav/footer links, OPEN local-preview bypass
---
build.mjs | 275 ++++++++++++++++++++++++++++++++++++++++++++++++
data/markets.json | 12 +--
data/news.json | 2 +-
data/ticker.json | 8 +-
public/about.html | 136 ++++++++++++++++++++++++
public/advertise.html | 145 +++++++++++++++++++++++++
public/conferences.html | 133 +++++++++++++++++++++++
public/index.html | 12 +--
public/subscribe.html | 137 ++++++++++++++++++++++++
server.js | 7 ++
10 files changed, 850 insertions(+), 17 deletions(-)
diff --git a/build.mjs b/build.mjs
new file mode 100644
index 0000000..0b37ebe
--- /dev/null
+++ b/build.mjs
@@ -0,0 +1,275 @@
+#!/usr/bin/env node
+// rentv-v1 page generator — emits the marketing/company pages (Conferences,
+// Advertise, Subscribe, About) that surround the live-news core, all sharing
+// ONE design-system shell so the whole site stays consistent. The live pages
+// (index/section/article/review/markets) are hand-authored + data-driven; this
+// generator owns only the static company pages. $0 (local).
+import { writeFileSync } from 'node:fs';
+import { dirname, join } from 'node:path';
+import { fileURLToPath } from 'node:url';
+const OUT = join(dirname(fileURLToPath(import.meta.url)), 'public');
+
+const BIZ = {
+ since: 1998,
+ addr: '5757 W. Century Blvd, Suite 700, Los Angeles, CA 90045',
+ phone: '(310) 213-6409',
+ email: 'info@rentv.com',
+};
+
+// ── Shared chrome (kept byte-identical in spirit to index.html's system) ──
+const CSS = `
+ :root{--red:#c8102e;--ink:#14171a;--sub:#5b636b;--line:#e4e7ea;--bg:#fff;--wash:#f5f6f8;--sans:'Inter',system-ui,sans-serif;--serif:'Playfair Display',Georgia,serif}
+ *{box-sizing:border-box;margin:0;padding:0}
+ body{font-family:var(--sans);color:var(--ink);background:var(--bg);line-height:1.5}
+ a{color:inherit;text-decoration:none}
+ .wrap{max-width:1200px;margin:0 auto;padding:0 20px}
+ .util{background:var(--ink);color:#cfd4d9;font-size:12px}
+ .util .wrap{display:flex;justify-content:space-between;align-items:center;height:34px}
+ .ticker{display:flex;gap:20px;overflow:hidden;white-space:nowrap}.ticker b{color:#fff}.up{color:#4ade80}.dn{color:#f87171}
+ .util .acts a{margin-left:14px;color:#cfd4d9}.util .acts a.sub{color:#fff;background:var(--red);padding:4px 12px;border-radius:3px;font-weight:700}
+ .mast{border-bottom:2px solid var(--ink);padding:20px 0 14px}
+ .mast .wrap{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;gap:3px}
+ .logo{font-family:var(--serif);font-weight:700;font-size:34px;letter-spacing:-1px}.logo span{color:var(--red)}
+ .logo small{display:block;font-size:11px;font-weight:600;letter-spacing:3px;color:var(--sub);text-transform:uppercase;margin-top:2px;font-family:var(--sans)}
+ .datebox{font-size:12px;color:var(--sub);text-align:center}
+ nav{border-bottom:1px solid var(--line);position:sticky;top:0;background:#fff;z-index:10}
+ nav .wrap{display:flex;gap:2px;align-items:center;height:46px}
+ .ham{display:none;background:none;border:0;font-size:24px;line-height:1;color:var(--ink);cursor:pointer;padding:8px 12px 8px 0;margin-right:4px}
+ .navlinks{display:flex;gap:2px;align-items:center;overflow-x:auto}
+ nav a{font-size:13px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;padding:14px 13px;border-bottom:3px solid transparent;white-space:nowrap;cursor:pointer}
+ nav a:hover,nav a.on{color:var(--red);border-color:var(--red)}
+ @media(max-width:860px){
+ .ham{display:block;order:-1}
+ nav .wrap{height:52px}
+ .navlinks{display:none;position:absolute;top:52px;left:0;right:0;background:#fff;flex-direction:column;align-items:stretch;border-bottom:2px solid var(--ink);box-shadow:0 10px 24px rgba(0,0,0,.14);z-index:30;max-height:78vh;overflow-y:auto}
+ .navlinks.open{display:flex}
+ .navlinks a{padding:15px 20px;border-bottom:1px solid var(--line);border-left:4px solid transparent}
+ .navlinks a:hover,.navlinks a.on{color:var(--red);border-bottom:1px solid var(--line);border-left-color:var(--red)}
+ }
+ .phero{background:linear-gradient(135deg,#111827,#c8102e);color:#fff;padding:54px 0}
+ .phero .k{font-size:12px;letter-spacing:.22em;text-transform:uppercase;opacity:.85;margin-bottom:12px}
+ .phero h1{font-family:var(--serif);font-size:clamp(32px,5vw,52px);line-height:1.08;letter-spacing:-.5px;max-width:20ch}
+ .phero p{max-width:60ch;margin-top:14px;font-size:17px;opacity:.94}
+ .rv{opacity:0;transform:translateY(18px);transition:opacity .6s ease,transform .6s ease}.rv.in{opacity:1;transform:none}
+ @media(prefers-reduced-motion:reduce){.rv{transition:none;opacity:1;transform:none}}
+ section.blk{padding:52px 0;border-bottom:1px solid var(--line)}
+ .eyebrow{font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.14em;color:var(--red);margin-bottom:10px}
+ h2.big{font-family:var(--serif);font-size:clamp(26px,3.4vw,38px);line-height:1.12;letter-spacing:-.4px;max-width:24ch}
+ .lead2{max-width:66ch;color:var(--sub);margin-top:12px;font-size:18px}
+ .cols3{display:grid;grid-template-columns:repeat(3,1fr);gap:22px;margin-top:30px}
+ .cols2{display:grid;grid-template-columns:1fr 1fr;gap:22px;margin-top:30px}
+ @media(max-width:860px){.cols3{grid-template-columns:1fr}.cols2{grid-template-columns:1fr}}
+ .tile{border:1px solid var(--line);border-radius:8px;padding:26px 24px;transition:.25s;background:#fff}
+ .tile:hover{transform:translateY(-4px);box-shadow:0 18px 44px rgba(0,0,0,.09);border-color:#cfd4d9}
+ .tile .n{font-family:var(--serif);font-size:15px;color:var(--red)}
+ .tile h3{font-family:var(--serif);font-size:22px;margin:8px 0 8px}
+ .tile p{color:var(--sub);font-size:15px}
+ .tile .price{margin-top:14px;font-size:13px;font-weight:800;text-transform:uppercase;letter-spacing:.05em;color:var(--ink)}
+ .statrow{display:flex;flex-wrap:wrap;gap:44px;margin-top:26px}
+ .statrow .v{font-family:var(--serif);font-size:40px;color:var(--red);line-height:1}
+ .statrow .l{font-size:12px;letter-spacing:.06em;text-transform:uppercase;color:var(--sub);margin-top:6px}
+ .cta{display:inline-block;background:var(--red);color:#fff;font-weight:800;font-size:13px;text-transform:uppercase;letter-spacing:.06em;padding:13px 26px;border-radius:5px;cursor:pointer;border:0;margin-top:22px}
+ .cta.ghost{background:transparent;color:var(--ink);border:1.5px solid var(--ink)}
+ .cta:hover{filter:brightness(1.06)}
+ .form{max-width:520px;margin-top:26px}
+ .form label{display:block;font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--sub);margin:14px 0 6px}
+ .form input,.form select{width:100%;padding:12px 14px;border:1px solid var(--line);border-radius:5px;font-size:15px;font-family:inherit}
+ .form .ok{display:none;margin-top:14px;padding:12px 16px;background:#ecfdf3;border:1px solid #a7f3d0;border-radius:6px;color:#067647;font-size:14px}
+ .kv{display:flex;justify-content:space-between;padding:11px 0;border-bottom:1px solid var(--line);font-size:15px}.kv b{font-weight:700}
+ footer{background:var(--ink);color:#aeb6bd;margin-top:0;padding:40px 0 30px;font-size:13px}
+ footer .cols{display:grid;grid-template-columns:2fr 1fr 1fr 1fr;gap:28px}
+ footer .logo{color:#fff;font-size:26px;margin-bottom:8px}footer h5{color:#fff;font-size:12px;text-transform:uppercase;letter-spacing:.08em;margin-bottom:10px}footer a{display:block;padding:4px 0;color:#aeb6bd}
+ footer .fine{border-top:1px solid #2a2f34;margin-top:26px;padding-top:16px;font-size:12px;color:#7c848b}
+ @media(max-width:860px){footer .cols{grid-template-columns:1fr 1fr}}
+`;
+
+const utilBar = `
+ <div class="util"><div class="wrap">
+ <div class="ticker" id="ticker"><span><b>CRE INDEX</b> …</span><span><b>10-YR</b> …</span><span><b>LA OFFICE VAC</b> …</span></div>
+ <div class="acts"><a href="/subscribe">Newsletters</a><a href="/advertise">Advertise</a><a href="/subscribe" class="sub">Subscribe</a></div>
+ </div></div>`;
+
+const masthead = `
+ <header class="mast"><div class="wrap">
+ <a class="logo" href="/">REN<span>TV</span>.com<small>Commercial Real Estate News</small></a>
+ <div class="datebox"><span>Western U.S. Edition</span><br><span id="today"></span></div>
+ </div></header>`;
+
+const NAV = [['/', 'Home'], ['/sales', 'Sales'], ['/leases', 'Leases'], ['/financing', 'Financing'], ['/development', 'Development'], ['/multifamily', 'Multifamily'], ['/industrial', 'Industrial'], ['/retail', 'Retail'], ['/review', 'The REview'], ['/conferences', 'Conferences']];
+const nav = (active) => `
+ <nav><div class="wrap">
+ <button class="ham" id="hamBtn" aria-label="Menu" aria-expanded="false">☰</button>
+ <div class="navlinks" id="nav">
+ ${NAV.map(([h, l]) => `<a href="${h}"${h === active ? ' class="on"' : ''}>${l}</a>`).join('')}
+ </div>
+ </div></nav>`;
+
+const footer = `
+ <footer><div class="wrap"><div class="cols">
+ <div><div class="logo">REN<span style="color:var(--red)">TV</span>.com</div><p style="max-width:34ch">Commercial real estate news, deals & conferences across the Western United States since ${BIZ.since}.</p></div>
+ <div><h5>Sections</h5><a href="/sales">Sales</a><a href="/leases">Leases</a><a href="/financing">Financing</a><a href="/development">Development</a></div>
+ <div><h5>Company</h5><a href="/about">About</a><a href="/advertise">Advertise</a><a href="/conferences">Conferences</a><a href="/subscribe">Subscribe</a></div>
+ <div><h5>Follow</h5><a href="https://www.linkedin.com/company/rentv.com-inc" target="_blank" rel="noopener">LinkedIn</a><a href="/review">The REview</a><a href="/subscribe">Newsletters</a></div>
+ </div><div class="fine">© ${new Date().getFullYear()} RENTV.com · ${BIZ.addr} · ${BIZ.phone}</div></div></footer>`;
+
+const baseJS = `
+ var t=document.getElementById('today');if(t)t.textContent=new Date().toLocaleDateString(undefined,{weekday:'long',year:'numeric',month:'long',day:'numeric'});
+ var hb=document.getElementById('hamBtn');if(hb)hb.addEventListener('click',function(){var o=document.getElementById('nav').classList.toggle('open');hb.setAttribute('aria-expanded',o);});
+ var esc=function(s){return (s||'').replace(/[&<>"]/g,function(c){return {'&':'&','<':'<','>':'>','"':'"'}[c];});};
+ (function(){fetch('/api/ticker').then(function(r){return r.json();}).then(function(t){
+ function cell(m){if(!m||!m.value)return '';var amt=m.change_pct!=null?Math.abs(m.change_pct)+'%':(m.change_bps!=null?Math.abs(m.change_bps)+'bps':'');var arr=m.dir==='up'?' <span class="up">▲'+amt+'</span>':(m.dir==='down'?' <span class="dn">▼'+amt+'</span>':'');return '<span><b>'+esc(m.label)+'</b> '+esc(m.value)+arr+'</span>';}
+ var h=[t.cre_index,t.ten_yr,t.la_office_vac,t.ie_industrial_cap].map(cell).filter(Boolean).join('');
+ var el=document.getElementById('ticker');if(h&&el)el.innerHTML=h;
+ }).catch(function(){});})();
+ var io=new IntersectionObserver(function(es){es.forEach(function(e){if(e.isIntersecting){e.target.classList.add('in');io.unobserve(e.target);}});},{threshold:.1});
+ document.querySelectorAll('.rv').forEach(function(el){io.observe(el);});
+ document.querySelectorAll('form[data-fakepost]').forEach(function(f){f.addEventListener('submit',function(e){e.preventDefault();var ok=f.querySelector('.ok');if(ok){ok.style.display='block';}f.querySelectorAll('input,select,button').forEach(function(x){if(x.type!=='reset')x.setAttribute('disabled','');});});});`;
+
+const page = (title, desc, active, main) => `<!doctype html>
+<html lang="en"><head>
+<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
+<title>${title} — RENTV.com</title>
+<meta name="description" content="${desc}">
+<link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,700;1,400&family=Inter:wght@300;400;600;800&display=swap" rel="stylesheet">
+<style>${CSS}</style></head><body>
+${utilBar}${masthead}${nav(active)}
+${main}
+${footer}
+<script>${baseJS}</script>
+</body></html>`;
+
+// ── Conferences ──
+const conferences = page('Conferences', 'RENTV Conferences — the State of the Market Summit franchise for Western-U.S. commercial real estate.', '/conferences', `
+ <div class="phero"><div class="wrap">
+ <div class="k">RENTV Conferences · since ${BIZ.since}</div>
+ <h1>The State of the Market Summit</h1>
+ <p>Where the Western-U.S. commercial real estate community meets — brokers, investors, developers and lenders, live, twice a year. The conference franchise behind RENTV.</p>
+ </div></div>
+ <section class="blk"><div class="wrap">
+ <div class="statrow rv">
+ <div><div class="v">600+</div><div class="l">CRE decision-makers per summit</div></div>
+ <div><div class="v">2×</div><div class="l">Flagship summits a year</div></div>
+ <div><div class="v">25+</div><div class="l">Years convening the market</div></div>
+ <div><div class="v">$175</div><div class="l">Standard delegate pass</div></div>
+ </div>
+ </div></section>
+ <section class="blk"><div class="wrap">
+ <div class="eyebrow rv">Upcoming</div><h2 class="big rv">Two rooms the whole market shows up for.</h2>
+ <div class="cols2">
+ <div class="tile rv"><div class="n">Fall 2026</div><h3>State of the Market — Los Angeles</h3><p>The flagship. Capital-markets outlook, office repositioning, industrial & multifamily deal flow, and the networking that actually closes deals.</p><div class="price">Delegate $175 · Sponsor packages available</div><a class="cta" href="/subscribe">Get date + registration alerts →</a></div>
+ <div class="tile rv"><div class="n">Spring 2027</div><h3>Capital & Development Forum</h3><p>The build-and-finance half of the calendar — construction lending, entitlements, and the projects breaking ground across the West.</p><div class="price">Delegate $175 · Sponsor packages available</div><a class="cta ghost" href="/advertise">Become a sponsor →</a></div>
+ </div>
+ </div></section>
+ <section class="blk"><div class="wrap">
+ <div class="eyebrow rv">Why sponsor</div><h2 class="big rv">Put your firm in front of the room that moves the market.</h2>
+ <p class="lead2 rv">Conference sponsorship pairs naturally with RENTV's newsletter and site audience — the same decision-makers, reached before, during, and after the event. Ask about integrated packages that bundle the summit with sponsored content and newsletter placement.</p>
+ <a class="cta rv" href="/advertise">Request the sponsor kit →</a>
+ </div></section>`);
+
+// ── Advertise (the modern media kit that replaces advertise.php) ──
+const advertise = page('Advertise', 'Reach Western-U.S. commercial real estate decision-makers through RENTV — newsletter, site, sponsored content, conferences and video.', '/advertise', `
+ <div class="phero"><div class="wrap">
+ <div class="k">Media Kit · ${new Date().getFullYear()}</div>
+ <h1>Reach the people who move Western-U.S. commercial real estate.</h1>
+ <p>Since ${BIZ.since}, RENTV has been where CRE professionals get their deals, financings and market intel. Put your firm in front of that audience across five integrated channels.</p>
+ </div></div>
+ <section class="blk"><div class="wrap">
+ <div class="eyebrow rv">The audience</div><h2 class="big rv">Decision-makers, not eyeballs.</h2>
+ <div class="statrow rv">
+ <div><div class="v">1998</div><div class="l">Trusted since</div></div>
+ <div><div class="v">Daily</div><div class="l">Newsletter cadence</div></div>
+ <div><div class="v">600+</div><div class="l">Live conference audience</div></div>
+ <div><div class="v">CRE</div><div class="l">100% industry-qualified</div></div>
+ </div>
+ </div></section>
+ <section class="blk"><div class="wrap">
+ <div class="eyebrow rv">Channels</div><h2 class="big rv">Five ways to reach the market — bundle for reach.</h2>
+ <div class="cols3">
+ <div class="tile rv"><div class="n">01</div><h3>Newsletter Sponsorship</h3><p>Top-of-inbox placement in the RENTV Daily — the single best way to reach active CRE professionals every morning.</p><div class="price">Weekly & monthly slots</div></div>
+ <div class="tile rv"><div class="n">02</div><h3>Site Display</h3><p>Leaderboard and in-feed units across the news river and section pages — always-on brand presence beside the deals.</p><div class="price">CPM & flat-rate</div></div>
+ <div class="tile rv"><div class="n">03</div><h3>Sponsored Content</h3><p>Native, RENTV-bylined articles that put your deal, product or point of view directly into the news feed.</p><div class="price">Per placement</div></div>
+ <div class="tile rv"><div class="n">04</div><h3>Conference Sponsorship</h3><p>Stage, booth and delegate access at the State of the Market summits — the room where deals actually close.</p><div class="price">Tiered packages</div></div>
+ <div class="tile rv"><div class="n">05</div><h3>Video & CRE Talk</h3><p>Pre-roll and named sponsorship on The REview and the CRE Talk interview series with regional CEOs.</p><div class="price">Series & per-episode</div></div>
+ <div class="tile rv"><div class="n">★</div><h3>Integrated Package</h3><p>Combine newsletter + content + conference for one campaign that surrounds the buyer across the whole month. Best value.</p><div class="price">Custom — ask us</div></div>
+ </div>
+ </div></section>
+ <section class="blk"><div class="wrap">
+ <div class="eyebrow rv">Get started</div><h2 class="big rv">Request the ${new Date().getFullYear()} media kit.</h2>
+ <p class="lead2 rv">Tell us a little about your firm and we'll send rates, audience data and available slots. No obligation.</p>
+ <form class="form rv" data-fakepost>
+ <label>Name</label><input required placeholder="Your name">
+ <label>Company</label><input required placeholder="Firm / brand">
+ <label>Work email</label><input type="email" required placeholder="you@company.com">
+ <label>Interested in</label><select><option>Integrated package</option><option>Newsletter sponsorship</option><option>Site display</option><option>Sponsored content</option><option>Conference sponsorship</option><option>Video / CRE Talk</option></select>
+ <button class="cta" type="submit">Request media kit →</button>
+ <div class="ok">✓ Thanks — the media kit is on its way. We'll be in touch within one business day.</div>
+ </form>
+ </div></section>`);
+
+// ── Subscribe (replaces subscriber_info.php) ──
+const subscribe = page('Subscribe', 'Get the free RENTV Daily — Western-U.S. commercial real estate deals, leases and financings in your inbox every morning.', '/subscribe', `
+ <div class="phero"><div class="wrap">
+ <div class="k">Free · Every weekday morning</div>
+ <h1>The RENTV Daily.</h1>
+ <p>Every Western-U.S. commercial real estate deal, lease and financing that matters — summarized and in your inbox before your first meeting. Free, since ${BIZ.since}.</p>
+ </div></div>
+ <section class="blk"><div class="wrap">
+ <div class="cols2">
+ <div class="rv">
+ <div class="eyebrow">What you get</div><h2 class="big">Written for people who close deals.</h2>
+ <div style="margin-top:22px">
+ <div class="kv"><span>The RENTV Daily</span><b>Every weekday · free</b></div>
+ <div class="kv"><span>Deal Alerts (Sales · Leases · Financing)</span><b>As they break</b></div>
+ <div class="kv"><span>Conference & event notices</span><b>Occasional</b></div>
+ <div class="kv"><span>The REview video digest</span><b>Weekly</b></div>
+ </div>
+ <p class="lead2" style="margin-top:20px">No spam, ever. One-click unsubscribe. Your address is never sold.</p>
+ </div>
+ <div class="tile rv" style="align-self:start">
+ <div class="n">Join free</div><h3>Start getting the Daily</h3>
+ <form class="form" data-fakepost style="margin-top:8px">
+ <label>Work email</label><input type="email" required placeholder="you@company.com">
+ <label>First name</label><input placeholder="First name">
+ <label>Primary interest</label><select><option>All Western-U.S. CRE</option><option>Sales</option><option>Leases</option><option>Financing</option><option>Development</option><option>Multifamily</option><option>Industrial</option><option>Retail</option></select>
+ <button class="cta" type="submit">Subscribe free →</button>
+ <div class="ok">✓ You're on the list. Watch for tomorrow's RENTV Daily.</div>
+ </form>
+ </div>
+ </div>
+ </div></section>`);
+
+// ── About ──
+const about = page('About', 'RENTV.com — commercial real estate news, video, and conferences for the Western United States since 1998.', '/about', `
+ <div class="phero"><div class="wrap">
+ <div class="k">About RENTV</div>
+ <h1>The Western-U.S. commercial real estate media company.</h1>
+ <p>Since ${BIZ.since}, RENTV has covered the deals, financings and developments shaping commercial real estate across the West — in news, video and live events.</p>
+ </div></div>
+ <section class="blk"><div class="wrap">
+ <div class="eyebrow rv">The portfolio</div><h2 class="big rv">One newsroom, four franchises.</h2>
+ <div class="cols2">
+ <div class="tile rv"><h3>RENTV News</h3><p>The daily record of Western-U.S. commercial real estate — sales, leases, financing, development and market intel, updated continuously.</p></div>
+ <div class="tile rv"><h3>The REview</h3><p>RENTV's video platform — market interviews, property features and deal breakdowns for people who'd rather watch than read.</p><a class="cta ghost" href="/review" style="margin-top:16px">Watch →</a></div>
+ <div class="tile rv"><h3>RENTV Conferences</h3><p>The State of the Market Summit franchise — the live rooms where the Western-U.S. CRE community meets twice a year.</p><a class="cta ghost" href="/conferences" style="margin-top:16px">See upcoming →</a></div>
+ <div class="tile rv"><h3>CRE Talk</h3><p>The interview series with the CEOs and principals steering the region's biggest firms — candid conversations on where the market is headed.</p></div>
+ </div>
+ </div></section>
+ <section class="blk"><div class="wrap">
+ <div class="eyebrow rv">Contact</div><h2 class="big rv">Reach the newsroom.</h2>
+ <div class="cols2">
+ <div class="rv">
+ <div class="kv"><span>Editorial & general</span><b>${BIZ.email}</b></div>
+ <div class="kv"><span>Phone</span><b>${BIZ.phone}</b></div>
+ <div class="kv"><span>Office</span><b>${BIZ.addr}</b></div>
+ <div class="kv"><span>Advertising</span><b><a href="/advertise" style="color:var(--red)">Request the media kit →</a></b></div>
+ </div>
+ <div class="tile rv"><div class="n">Tip the newsroom</div><h3>Have a deal for us?</h3><p>Sales, leases, financings and groundbreakings — send it over and our editors will take a look.</p>
+ <form class="form" data-fakepost style="margin-top:8px"><label>Your email</label><input type="email" required placeholder="you@company.com"><label>The tip</label><input required placeholder="What's the deal?"><button class="cta" type="submit">Send tip →</button><div class="ok">✓ Got it — thanks. Our editors will follow up if we need more.</div></form>
+ </div>
+ </div>
+ </div></section>`);
+
+const pages = { 'conferences.html': conferences, 'advertise.html': advertise, 'subscribe.html': subscribe, 'about.html': about };
+for (const [f, html] of Object.entries(pages)) writeFileSync(join(OUT, f), html);
+console.log('Wrote company pages: ' + Object.keys(pages).join(', '));
diff --git a/data/markets.json b/data/markets.json
index da1265c..1a68b3c 100644
--- a/data/markets.json
+++ b/data/markets.json
@@ -1,5 +1,5 @@
{
- "fetched_at": "2026-07-21T19:23:26.799Z",
+ "fetched_at": "2026-07-21T19:43:27.705Z",
"source": "Yahoo Finance — live (CBOE Treasury yields, Dow Jones/MSCI REIT indices)",
"curve": [
{
@@ -42,9 +42,9 @@
"reits": [
{
"label": "DJ U.S. Real Estate",
- "value": "397.40",
- "change_pct": -0.06,
- "dir": "down"
+ "value": "397.65",
+ "change_pct": 0.01,
+ "dir": "up"
},
{
"label": "MSCI U.S. REIT",
@@ -54,8 +54,8 @@
},
{
"label": "Vanguard REIT ETF (VNQ)",
- "value": "$99.47",
- "change_pct": -0.55,
+ "value": "$99.52",
+ "change_pct": -0.5,
"dir": "down"
}
],
diff --git a/data/news.json b/data/news.json
index db29822..3622458 100644
--- a/data/news.json
+++ b/data/news.json
@@ -1,6 +1,6 @@
{
"source": "rentv.com — live",
- "fetched_at": "2026-07-21T19:23:26.471Z",
+ "fetched_at": "2026-07-21T19:43:27.351Z",
"count": 30,
"items": [
{
diff --git a/data/ticker.json b/data/ticker.json
index 083cd1e..b7ff6ee 100644
--- a/data/ticker.json
+++ b/data/ticker.json
@@ -1,5 +1,5 @@
{
- "fetched_at": "2026-07-21T19:23:26.770Z",
+ "fetched_at": "2026-07-21T19:43:27.673Z",
"la_office_vac": {
"label": "LA OFFICE VAC",
"value": "23.1%",
@@ -14,9 +14,9 @@
},
"cre_index": {
"label": "CRE INDEX",
- "value": "4,177",
- "change_pct": -0.06,
- "dir": "down",
+ "value": "4,179",
+ "change_pct": 0.01,
+ "dir": "up",
"source": "Dow Jones U.S. Real Estate"
},
"ten_yr": {
diff --git a/public/about.html b/public/about.html
new file mode 100644
index 0000000..4528607
--- /dev/null
+++ b/public/about.html
@@ -0,0 +1,136 @@
+<!doctype html>
+<html lang="en"><head>
+<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
+<title>About — RENTV.com</title>
+<meta name="description" content="RENTV.com — commercial real estate news, video, and conferences for the Western United States since 1998.">
+<link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,700;1,400&family=Inter:wght@300;400;600;800&display=swap" rel="stylesheet">
+<style>
+ :root{--red:#c8102e;--ink:#14171a;--sub:#5b636b;--line:#e4e7ea;--bg:#fff;--wash:#f5f6f8;--sans:'Inter',system-ui,sans-serif;--serif:'Playfair Display',Georgia,serif}
+ *{box-sizing:border-box;margin:0;padding:0}
+ body{font-family:var(--sans);color:var(--ink);background:var(--bg);line-height:1.5}
+ a{color:inherit;text-decoration:none}
+ .wrap{max-width:1200px;margin:0 auto;padding:0 20px}
+ .util{background:var(--ink);color:#cfd4d9;font-size:12px}
+ .util .wrap{display:flex;justify-content:space-between;align-items:center;height:34px}
+ .ticker{display:flex;gap:20px;overflow:hidden;white-space:nowrap}.ticker b{color:#fff}.up{color:#4ade80}.dn{color:#f87171}
+ .util .acts a{margin-left:14px;color:#cfd4d9}.util .acts a.sub{color:#fff;background:var(--red);padding:4px 12px;border-radius:3px;font-weight:700}
+ .mast{border-bottom:2px solid var(--ink);padding:20px 0 14px}
+ .mast .wrap{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;gap:3px}
+ .logo{font-family:var(--serif);font-weight:700;font-size:34px;letter-spacing:-1px}.logo span{color:var(--red)}
+ .logo small{display:block;font-size:11px;font-weight:600;letter-spacing:3px;color:var(--sub);text-transform:uppercase;margin-top:2px;font-family:var(--sans)}
+ .datebox{font-size:12px;color:var(--sub);text-align:center}
+ nav{border-bottom:1px solid var(--line);position:sticky;top:0;background:#fff;z-index:10}
+ nav .wrap{display:flex;gap:2px;align-items:center;height:46px}
+ .ham{display:none;background:none;border:0;font-size:24px;line-height:1;color:var(--ink);cursor:pointer;padding:8px 12px 8px 0;margin-right:4px}
+ .navlinks{display:flex;gap:2px;align-items:center;overflow-x:auto}
+ nav a{font-size:13px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;padding:14px 13px;border-bottom:3px solid transparent;white-space:nowrap;cursor:pointer}
+ nav a:hover,nav a.on{color:var(--red);border-color:var(--red)}
+ @media(max-width:860px){
+ .ham{display:block;order:-1}
+ nav .wrap{height:52px}
+ .navlinks{display:none;position:absolute;top:52px;left:0;right:0;background:#fff;flex-direction:column;align-items:stretch;border-bottom:2px solid var(--ink);box-shadow:0 10px 24px rgba(0,0,0,.14);z-index:30;max-height:78vh;overflow-y:auto}
+ .navlinks.open{display:flex}
+ .navlinks a{padding:15px 20px;border-bottom:1px solid var(--line);border-left:4px solid transparent}
+ .navlinks a:hover,.navlinks a.on{color:var(--red);border-bottom:1px solid var(--line);border-left-color:var(--red)}
+ }
+ .phero{background:linear-gradient(135deg,#111827,#c8102e);color:#fff;padding:54px 0}
+ .phero .k{font-size:12px;letter-spacing:.22em;text-transform:uppercase;opacity:.85;margin-bottom:12px}
+ .phero h1{font-family:var(--serif);font-size:clamp(32px,5vw,52px);line-height:1.08;letter-spacing:-.5px;max-width:20ch}
+ .phero p{max-width:60ch;margin-top:14px;font-size:17px;opacity:.94}
+ .rv{opacity:0;transform:translateY(18px);transition:opacity .6s ease,transform .6s ease}.rv.in{opacity:1;transform:none}
+ @media(prefers-reduced-motion:reduce){.rv{transition:none;opacity:1;transform:none}}
+ section.blk{padding:52px 0;border-bottom:1px solid var(--line)}
+ .eyebrow{font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.14em;color:var(--red);margin-bottom:10px}
+ h2.big{font-family:var(--serif);font-size:clamp(26px,3.4vw,38px);line-height:1.12;letter-spacing:-.4px;max-width:24ch}
+ .lead2{max-width:66ch;color:var(--sub);margin-top:12px;font-size:18px}
+ .cols3{display:grid;grid-template-columns:repeat(3,1fr);gap:22px;margin-top:30px}
+ .cols2{display:grid;grid-template-columns:1fr 1fr;gap:22px;margin-top:30px}
+ @media(max-width:860px){.cols3{grid-template-columns:1fr}.cols2{grid-template-columns:1fr}}
+ .tile{border:1px solid var(--line);border-radius:8px;padding:26px 24px;transition:.25s;background:#fff}
+ .tile:hover{transform:translateY(-4px);box-shadow:0 18px 44px rgba(0,0,0,.09);border-color:#cfd4d9}
+ .tile .n{font-family:var(--serif);font-size:15px;color:var(--red)}
+ .tile h3{font-family:var(--serif);font-size:22px;margin:8px 0 8px}
+ .tile p{color:var(--sub);font-size:15px}
+ .tile .price{margin-top:14px;font-size:13px;font-weight:800;text-transform:uppercase;letter-spacing:.05em;color:var(--ink)}
+ .statrow{display:flex;flex-wrap:wrap;gap:44px;margin-top:26px}
+ .statrow .v{font-family:var(--serif);font-size:40px;color:var(--red);line-height:1}
+ .statrow .l{font-size:12px;letter-spacing:.06em;text-transform:uppercase;color:var(--sub);margin-top:6px}
+ .cta{display:inline-block;background:var(--red);color:#fff;font-weight:800;font-size:13px;text-transform:uppercase;letter-spacing:.06em;padding:13px 26px;border-radius:5px;cursor:pointer;border:0;margin-top:22px}
+ .cta.ghost{background:transparent;color:var(--ink);border:1.5px solid var(--ink)}
+ .cta:hover{filter:brightness(1.06)}
+ .form{max-width:520px;margin-top:26px}
+ .form label{display:block;font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--sub);margin:14px 0 6px}
+ .form input,.form select{width:100%;padding:12px 14px;border:1px solid var(--line);border-radius:5px;font-size:15px;font-family:inherit}
+ .form .ok{display:none;margin-top:14px;padding:12px 16px;background:#ecfdf3;border:1px solid #a7f3d0;border-radius:6px;color:#067647;font-size:14px}
+ .kv{display:flex;justify-content:space-between;padding:11px 0;border-bottom:1px solid var(--line);font-size:15px}.kv b{font-weight:700}
+ footer{background:var(--ink);color:#aeb6bd;margin-top:0;padding:40px 0 30px;font-size:13px}
+ footer .cols{display:grid;grid-template-columns:2fr 1fr 1fr 1fr;gap:28px}
+ footer .logo{color:#fff;font-size:26px;margin-bottom:8px}footer h5{color:#fff;font-size:12px;text-transform:uppercase;letter-spacing:.08em;margin-bottom:10px}footer a{display:block;padding:4px 0;color:#aeb6bd}
+ footer .fine{border-top:1px solid #2a2f34;margin-top:26px;padding-top:16px;font-size:12px;color:#7c848b}
+ @media(max-width:860px){footer .cols{grid-template-columns:1fr 1fr}}
+</style></head><body>
+
+ <div class="util"><div class="wrap">
+ <div class="ticker" id="ticker"><span><b>CRE INDEX</b> …</span><span><b>10-YR</b> …</span><span><b>LA OFFICE VAC</b> …</span></div>
+ <div class="acts"><a href="/subscribe">Newsletters</a><a href="/advertise">Advertise</a><a href="/subscribe" class="sub">Subscribe</a></div>
+ </div></div>
+ <header class="mast"><div class="wrap">
+ <a class="logo" href="/">REN<span>TV</span>.com<small>Commercial Real Estate News</small></a>
+ <div class="datebox"><span>Western U.S. Edition</span><br><span id="today"></span></div>
+ </div></header>
+ <nav><div class="wrap">
+ <button class="ham" id="hamBtn" aria-label="Menu" aria-expanded="false">☰</button>
+ <div class="navlinks" id="nav">
+ <a href="/">Home</a><a href="/sales">Sales</a><a href="/leases">Leases</a><a href="/financing">Financing</a><a href="/development">Development</a><a href="/multifamily">Multifamily</a><a href="/industrial">Industrial</a><a href="/retail">Retail</a><a href="/review">The REview</a><a href="/conferences">Conferences</a>
+ </div>
+ </div></nav>
+
+ <div class="phero"><div class="wrap">
+ <div class="k">About RENTV</div>
+ <h1>The Western-U.S. commercial real estate media company.</h1>
+ <p>Since 1998, RENTV has covered the deals, financings and developments shaping commercial real estate across the West — in news, video and live events.</p>
+ </div></div>
+ <section class="blk"><div class="wrap">
+ <div class="eyebrow rv">The portfolio</div><h2 class="big rv">One newsroom, four franchises.</h2>
+ <div class="cols2">
+ <div class="tile rv"><h3>RENTV News</h3><p>The daily record of Western-U.S. commercial real estate — sales, leases, financing, development and market intel, updated continuously.</p></div>
+ <div class="tile rv"><h3>The REview</h3><p>RENTV's video platform — market interviews, property features and deal breakdowns for people who'd rather watch than read.</p><a class="cta ghost" href="/review" style="margin-top:16px">Watch →</a></div>
+ <div class="tile rv"><h3>RENTV Conferences</h3><p>The State of the Market Summit franchise — the live rooms where the Western-U.S. CRE community meets twice a year.</p><a class="cta ghost" href="/conferences" style="margin-top:16px">See upcoming →</a></div>
+ <div class="tile rv"><h3>CRE Talk</h3><p>The interview series with the CEOs and principals steering the region's biggest firms — candid conversations on where the market is headed.</p></div>
+ </div>
+ </div></section>
+ <section class="blk"><div class="wrap">
+ <div class="eyebrow rv">Contact</div><h2 class="big rv">Reach the newsroom.</h2>
+ <div class="cols2">
+ <div class="rv">
+ <div class="kv"><span>Editorial & general</span><b>info@rentv.com</b></div>
+ <div class="kv"><span>Phone</span><b>(310) 213-6409</b></div>
+ <div class="kv"><span>Office</span><b>5757 W. Century Blvd, Suite 700, Los Angeles, CA 90045</b></div>
+ <div class="kv"><span>Advertising</span><b><a href="/advertise" style="color:var(--red)">Request the media kit →</a></b></div>
+ </div>
+ <div class="tile rv"><div class="n">Tip the newsroom</div><h3>Have a deal for us?</h3><p>Sales, leases, financings and groundbreakings — send it over and our editors will take a look.</p>
+ <form class="form" data-fakepost style="margin-top:8px"><label>Your email</label><input type="email" required placeholder="you@company.com"><label>The tip</label><input required placeholder="What's the deal?"><button class="cta" type="submit">Send tip →</button><div class="ok">✓ Got it — thanks. Our editors will follow up if we need more.</div></form>
+ </div>
+ </div>
+ </div></section>
+
+ <footer><div class="wrap"><div class="cols">
+ <div><div class="logo">REN<span style="color:var(--red)">TV</span>.com</div><p style="max-width:34ch">Commercial real estate news, deals & conferences across the Western United States since 1998.</p></div>
+ <div><h5>Sections</h5><a href="/sales">Sales</a><a href="/leases">Leases</a><a href="/financing">Financing</a><a href="/development">Development</a></div>
+ <div><h5>Company</h5><a href="/about">About</a><a href="/advertise">Advertise</a><a href="/conferences">Conferences</a><a href="/subscribe">Subscribe</a></div>
+ <div><h5>Follow</h5><a href="https://www.linkedin.com/company/rentv.com-inc" target="_blank" rel="noopener">LinkedIn</a><a href="/review">The REview</a><a href="/subscribe">Newsletters</a></div>
+ </div><div class="fine">© 2026 RENTV.com · 5757 W. Century Blvd, Suite 700, Los Angeles, CA 90045 · (310) 213-6409</div></div></footer>
+<script>
+ var t=document.getElementById('today');if(t)t.textContent=new Date().toLocaleDateString(undefined,{weekday:'long',year:'numeric',month:'long',day:'numeric'});
+ var hb=document.getElementById('hamBtn');if(hb)hb.addEventListener('click',function(){var o=document.getElementById('nav').classList.toggle('open');hb.setAttribute('aria-expanded',o);});
+ var esc=function(s){return (s||'').replace(/[&<>"]/g,function(c){return {'&':'&','<':'<','>':'>','"':'"'}[c];});};
+ (function(){fetch('/api/ticker').then(function(r){return r.json();}).then(function(t){
+ function cell(m){if(!m||!m.value)return '';var amt=m.change_pct!=null?Math.abs(m.change_pct)+'%':(m.change_bps!=null?Math.abs(m.change_bps)+'bps':'');var arr=m.dir==='up'?' <span class="up">▲'+amt+'</span>':(m.dir==='down'?' <span class="dn">▼'+amt+'</span>':'');return '<span><b>'+esc(m.label)+'</b> '+esc(m.value)+arr+'</span>';}
+ var h=[t.cre_index,t.ten_yr,t.la_office_vac,t.ie_industrial_cap].map(cell).filter(Boolean).join('');
+ var el=document.getElementById('ticker');if(h&&el)el.innerHTML=h;
+ }).catch(function(){});})();
+ var io=new IntersectionObserver(function(es){es.forEach(function(e){if(e.isIntersecting){e.target.classList.add('in');io.unobserve(e.target);}});},{threshold:.1});
+ document.querySelectorAll('.rv').forEach(function(el){io.observe(el);});
+ document.querySelectorAll('form[data-fakepost]').forEach(function(f){f.addEventListener('submit',function(e){e.preventDefault();var ok=f.querySelector('.ok');if(ok){ok.style.display='block';}f.querySelectorAll('input,select,button').forEach(function(x){if(x.type!=='reset')x.setAttribute('disabled','');});});});</script>
+</body></html>
\ No newline at end of file
diff --git a/public/advertise.html b/public/advertise.html
new file mode 100644
index 0000000..e4ed2f7
--- /dev/null
+++ b/public/advertise.html
@@ -0,0 +1,145 @@
+<!doctype html>
+<html lang="en"><head>
+<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
+<title>Advertise — RENTV.com</title>
+<meta name="description" content="Reach Western-U.S. commercial real estate decision-makers through RENTV — newsletter, site, sponsored content, conferences and video.">
+<link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,700;1,400&family=Inter:wght@300;400;600;800&display=swap" rel="stylesheet">
+<style>
+ :root{--red:#c8102e;--ink:#14171a;--sub:#5b636b;--line:#e4e7ea;--bg:#fff;--wash:#f5f6f8;--sans:'Inter',system-ui,sans-serif;--serif:'Playfair Display',Georgia,serif}
+ *{box-sizing:border-box;margin:0;padding:0}
+ body{font-family:var(--sans);color:var(--ink);background:var(--bg);line-height:1.5}
+ a{color:inherit;text-decoration:none}
+ .wrap{max-width:1200px;margin:0 auto;padding:0 20px}
+ .util{background:var(--ink);color:#cfd4d9;font-size:12px}
+ .util .wrap{display:flex;justify-content:space-between;align-items:center;height:34px}
+ .ticker{display:flex;gap:20px;overflow:hidden;white-space:nowrap}.ticker b{color:#fff}.up{color:#4ade80}.dn{color:#f87171}
+ .util .acts a{margin-left:14px;color:#cfd4d9}.util .acts a.sub{color:#fff;background:var(--red);padding:4px 12px;border-radius:3px;font-weight:700}
+ .mast{border-bottom:2px solid var(--ink);padding:20px 0 14px}
+ .mast .wrap{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;gap:3px}
+ .logo{font-family:var(--serif);font-weight:700;font-size:34px;letter-spacing:-1px}.logo span{color:var(--red)}
+ .logo small{display:block;font-size:11px;font-weight:600;letter-spacing:3px;color:var(--sub);text-transform:uppercase;margin-top:2px;font-family:var(--sans)}
+ .datebox{font-size:12px;color:var(--sub);text-align:center}
+ nav{border-bottom:1px solid var(--line);position:sticky;top:0;background:#fff;z-index:10}
+ nav .wrap{display:flex;gap:2px;align-items:center;height:46px}
+ .ham{display:none;background:none;border:0;font-size:24px;line-height:1;color:var(--ink);cursor:pointer;padding:8px 12px 8px 0;margin-right:4px}
+ .navlinks{display:flex;gap:2px;align-items:center;overflow-x:auto}
+ nav a{font-size:13px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;padding:14px 13px;border-bottom:3px solid transparent;white-space:nowrap;cursor:pointer}
+ nav a:hover,nav a.on{color:var(--red);border-color:var(--red)}
+ @media(max-width:860px){
+ .ham{display:block;order:-1}
+ nav .wrap{height:52px}
+ .navlinks{display:none;position:absolute;top:52px;left:0;right:0;background:#fff;flex-direction:column;align-items:stretch;border-bottom:2px solid var(--ink);box-shadow:0 10px 24px rgba(0,0,0,.14);z-index:30;max-height:78vh;overflow-y:auto}
+ .navlinks.open{display:flex}
+ .navlinks a{padding:15px 20px;border-bottom:1px solid var(--line);border-left:4px solid transparent}
+ .navlinks a:hover,.navlinks a.on{color:var(--red);border-bottom:1px solid var(--line);border-left-color:var(--red)}
+ }
+ .phero{background:linear-gradient(135deg,#111827,#c8102e);color:#fff;padding:54px 0}
+ .phero .k{font-size:12px;letter-spacing:.22em;text-transform:uppercase;opacity:.85;margin-bottom:12px}
+ .phero h1{font-family:var(--serif);font-size:clamp(32px,5vw,52px);line-height:1.08;letter-spacing:-.5px;max-width:20ch}
+ .phero p{max-width:60ch;margin-top:14px;font-size:17px;opacity:.94}
+ .rv{opacity:0;transform:translateY(18px);transition:opacity .6s ease,transform .6s ease}.rv.in{opacity:1;transform:none}
+ @media(prefers-reduced-motion:reduce){.rv{transition:none;opacity:1;transform:none}}
+ section.blk{padding:52px 0;border-bottom:1px solid var(--line)}
+ .eyebrow{font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.14em;color:var(--red);margin-bottom:10px}
+ h2.big{font-family:var(--serif);font-size:clamp(26px,3.4vw,38px);line-height:1.12;letter-spacing:-.4px;max-width:24ch}
+ .lead2{max-width:66ch;color:var(--sub);margin-top:12px;font-size:18px}
+ .cols3{display:grid;grid-template-columns:repeat(3,1fr);gap:22px;margin-top:30px}
+ .cols2{display:grid;grid-template-columns:1fr 1fr;gap:22px;margin-top:30px}
+ @media(max-width:860px){.cols3{grid-template-columns:1fr}.cols2{grid-template-columns:1fr}}
+ .tile{border:1px solid var(--line);border-radius:8px;padding:26px 24px;transition:.25s;background:#fff}
+ .tile:hover{transform:translateY(-4px);box-shadow:0 18px 44px rgba(0,0,0,.09);border-color:#cfd4d9}
+ .tile .n{font-family:var(--serif);font-size:15px;color:var(--red)}
+ .tile h3{font-family:var(--serif);font-size:22px;margin:8px 0 8px}
+ .tile p{color:var(--sub);font-size:15px}
+ .tile .price{margin-top:14px;font-size:13px;font-weight:800;text-transform:uppercase;letter-spacing:.05em;color:var(--ink)}
+ .statrow{display:flex;flex-wrap:wrap;gap:44px;margin-top:26px}
+ .statrow .v{font-family:var(--serif);font-size:40px;color:var(--red);line-height:1}
+ .statrow .l{font-size:12px;letter-spacing:.06em;text-transform:uppercase;color:var(--sub);margin-top:6px}
+ .cta{display:inline-block;background:var(--red);color:#fff;font-weight:800;font-size:13px;text-transform:uppercase;letter-spacing:.06em;padding:13px 26px;border-radius:5px;cursor:pointer;border:0;margin-top:22px}
+ .cta.ghost{background:transparent;color:var(--ink);border:1.5px solid var(--ink)}
+ .cta:hover{filter:brightness(1.06)}
+ .form{max-width:520px;margin-top:26px}
+ .form label{display:block;font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--sub);margin:14px 0 6px}
+ .form input,.form select{width:100%;padding:12px 14px;border:1px solid var(--line);border-radius:5px;font-size:15px;font-family:inherit}
+ .form .ok{display:none;margin-top:14px;padding:12px 16px;background:#ecfdf3;border:1px solid #a7f3d0;border-radius:6px;color:#067647;font-size:14px}
+ .kv{display:flex;justify-content:space-between;padding:11px 0;border-bottom:1px solid var(--line);font-size:15px}.kv b{font-weight:700}
+ footer{background:var(--ink);color:#aeb6bd;margin-top:0;padding:40px 0 30px;font-size:13px}
+ footer .cols{display:grid;grid-template-columns:2fr 1fr 1fr 1fr;gap:28px}
+ footer .logo{color:#fff;font-size:26px;margin-bottom:8px}footer h5{color:#fff;font-size:12px;text-transform:uppercase;letter-spacing:.08em;margin-bottom:10px}footer a{display:block;padding:4px 0;color:#aeb6bd}
+ footer .fine{border-top:1px solid #2a2f34;margin-top:26px;padding-top:16px;font-size:12px;color:#7c848b}
+ @media(max-width:860px){footer .cols{grid-template-columns:1fr 1fr}}
+</style></head><body>
+
+ <div class="util"><div class="wrap">
+ <div class="ticker" id="ticker"><span><b>CRE INDEX</b> …</span><span><b>10-YR</b> …</span><span><b>LA OFFICE VAC</b> …</span></div>
+ <div class="acts"><a href="/subscribe">Newsletters</a><a href="/advertise">Advertise</a><a href="/subscribe" class="sub">Subscribe</a></div>
+ </div></div>
+ <header class="mast"><div class="wrap">
+ <a class="logo" href="/">REN<span>TV</span>.com<small>Commercial Real Estate News</small></a>
+ <div class="datebox"><span>Western U.S. Edition</span><br><span id="today"></span></div>
+ </div></header>
+ <nav><div class="wrap">
+ <button class="ham" id="hamBtn" aria-label="Menu" aria-expanded="false">☰</button>
+ <div class="navlinks" id="nav">
+ <a href="/">Home</a><a href="/sales">Sales</a><a href="/leases">Leases</a><a href="/financing">Financing</a><a href="/development">Development</a><a href="/multifamily">Multifamily</a><a href="/industrial">Industrial</a><a href="/retail">Retail</a><a href="/review">The REview</a><a href="/conferences">Conferences</a>
+ </div>
+ </div></nav>
+
+ <div class="phero"><div class="wrap">
+ <div class="k">Media Kit · 2026</div>
+ <h1>Reach the people who move Western-U.S. commercial real estate.</h1>
+ <p>Since 1998, RENTV has been where CRE professionals get their deals, financings and market intel. Put your firm in front of that audience across five integrated channels.</p>
+ </div></div>
+ <section class="blk"><div class="wrap">
+ <div class="eyebrow rv">The audience</div><h2 class="big rv">Decision-makers, not eyeballs.</h2>
+ <div class="statrow rv">
+ <div><div class="v">1998</div><div class="l">Trusted since</div></div>
+ <div><div class="v">Daily</div><div class="l">Newsletter cadence</div></div>
+ <div><div class="v">600+</div><div class="l">Live conference audience</div></div>
+ <div><div class="v">CRE</div><div class="l">100% industry-qualified</div></div>
+ </div>
+ </div></section>
+ <section class="blk"><div class="wrap">
+ <div class="eyebrow rv">Channels</div><h2 class="big rv">Five ways to reach the market — bundle for reach.</h2>
+ <div class="cols3">
+ <div class="tile rv"><div class="n">01</div><h3>Newsletter Sponsorship</h3><p>Top-of-inbox placement in the RENTV Daily — the single best way to reach active CRE professionals every morning.</p><div class="price">Weekly & monthly slots</div></div>
+ <div class="tile rv"><div class="n">02</div><h3>Site Display</h3><p>Leaderboard and in-feed units across the news river and section pages — always-on brand presence beside the deals.</p><div class="price">CPM & flat-rate</div></div>
+ <div class="tile rv"><div class="n">03</div><h3>Sponsored Content</h3><p>Native, RENTV-bylined articles that put your deal, product or point of view directly into the news feed.</p><div class="price">Per placement</div></div>
+ <div class="tile rv"><div class="n">04</div><h3>Conference Sponsorship</h3><p>Stage, booth and delegate access at the State of the Market summits — the room where deals actually close.</p><div class="price">Tiered packages</div></div>
+ <div class="tile rv"><div class="n">05</div><h3>Video & CRE Talk</h3><p>Pre-roll and named sponsorship on The REview and the CRE Talk interview series with regional CEOs.</p><div class="price">Series & per-episode</div></div>
+ <div class="tile rv"><div class="n">★</div><h3>Integrated Package</h3><p>Combine newsletter + content + conference for one campaign that surrounds the buyer across the whole month. Best value.</p><div class="price">Custom — ask us</div></div>
+ </div>
+ </div></section>
+ <section class="blk"><div class="wrap">
+ <div class="eyebrow rv">Get started</div><h2 class="big rv">Request the 2026 media kit.</h2>
+ <p class="lead2 rv">Tell us a little about your firm and we'll send rates, audience data and available slots. No obligation.</p>
+ <form class="form rv" data-fakepost>
+ <label>Name</label><input required placeholder="Your name">
+ <label>Company</label><input required placeholder="Firm / brand">
+ <label>Work email</label><input type="email" required placeholder="you@company.com">
+ <label>Interested in</label><select><option>Integrated package</option><option>Newsletter sponsorship</option><option>Site display</option><option>Sponsored content</option><option>Conference sponsorship</option><option>Video / CRE Talk</option></select>
+ <button class="cta" type="submit">Request media kit →</button>
+ <div class="ok">✓ Thanks — the media kit is on its way. We'll be in touch within one business day.</div>
+ </form>
+ </div></section>
+
+ <footer><div class="wrap"><div class="cols">
+ <div><div class="logo">REN<span style="color:var(--red)">TV</span>.com</div><p style="max-width:34ch">Commercial real estate news, deals & conferences across the Western United States since 1998.</p></div>
+ <div><h5>Sections</h5><a href="/sales">Sales</a><a href="/leases">Leases</a><a href="/financing">Financing</a><a href="/development">Development</a></div>
+ <div><h5>Company</h5><a href="/about">About</a><a href="/advertise">Advertise</a><a href="/conferences">Conferences</a><a href="/subscribe">Subscribe</a></div>
+ <div><h5>Follow</h5><a href="https://www.linkedin.com/company/rentv.com-inc" target="_blank" rel="noopener">LinkedIn</a><a href="/review">The REview</a><a href="/subscribe">Newsletters</a></div>
+ </div><div class="fine">© 2026 RENTV.com · 5757 W. Century Blvd, Suite 700, Los Angeles, CA 90045 · (310) 213-6409</div></div></footer>
+<script>
+ var t=document.getElementById('today');if(t)t.textContent=new Date().toLocaleDateString(undefined,{weekday:'long',year:'numeric',month:'long',day:'numeric'});
+ var hb=document.getElementById('hamBtn');if(hb)hb.addEventListener('click',function(){var o=document.getElementById('nav').classList.toggle('open');hb.setAttribute('aria-expanded',o);});
+ var esc=function(s){return (s||'').replace(/[&<>"]/g,function(c){return {'&':'&','<':'<','>':'>','"':'"'}[c];});};
+ (function(){fetch('/api/ticker').then(function(r){return r.json();}).then(function(t){
+ function cell(m){if(!m||!m.value)return '';var amt=m.change_pct!=null?Math.abs(m.change_pct)+'%':(m.change_bps!=null?Math.abs(m.change_bps)+'bps':'');var arr=m.dir==='up'?' <span class="up">▲'+amt+'</span>':(m.dir==='down'?' <span class="dn">▼'+amt+'</span>':'');return '<span><b>'+esc(m.label)+'</b> '+esc(m.value)+arr+'</span>';}
+ var h=[t.cre_index,t.ten_yr,t.la_office_vac,t.ie_industrial_cap].map(cell).filter(Boolean).join('');
+ var el=document.getElementById('ticker');if(h&&el)el.innerHTML=h;
+ }).catch(function(){});})();
+ var io=new IntersectionObserver(function(es){es.forEach(function(e){if(e.isIntersecting){e.target.classList.add('in');io.unobserve(e.target);}});},{threshold:.1});
+ document.querySelectorAll('.rv').forEach(function(el){io.observe(el);});
+ document.querySelectorAll('form[data-fakepost]').forEach(function(f){f.addEventListener('submit',function(e){e.preventDefault();var ok=f.querySelector('.ok');if(ok){ok.style.display='block';}f.querySelectorAll('input,select,button').forEach(function(x){if(x.type!=='reset')x.setAttribute('disabled','');});});});</script>
+</body></html>
\ No newline at end of file
diff --git a/public/conferences.html b/public/conferences.html
new file mode 100644
index 0000000..3e95450
--- /dev/null
+++ b/public/conferences.html
@@ -0,0 +1,133 @@
+<!doctype html>
+<html lang="en"><head>
+<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
+<title>Conferences — RENTV.com</title>
+<meta name="description" content="RENTV Conferences — the State of the Market Summit franchise for Western-U.S. commercial real estate.">
+<link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,700;1,400&family=Inter:wght@300;400;600;800&display=swap" rel="stylesheet">
+<style>
+ :root{--red:#c8102e;--ink:#14171a;--sub:#5b636b;--line:#e4e7ea;--bg:#fff;--wash:#f5f6f8;--sans:'Inter',system-ui,sans-serif;--serif:'Playfair Display',Georgia,serif}
+ *{box-sizing:border-box;margin:0;padding:0}
+ body{font-family:var(--sans);color:var(--ink);background:var(--bg);line-height:1.5}
+ a{color:inherit;text-decoration:none}
+ .wrap{max-width:1200px;margin:0 auto;padding:0 20px}
+ .util{background:var(--ink);color:#cfd4d9;font-size:12px}
+ .util .wrap{display:flex;justify-content:space-between;align-items:center;height:34px}
+ .ticker{display:flex;gap:20px;overflow:hidden;white-space:nowrap}.ticker b{color:#fff}.up{color:#4ade80}.dn{color:#f87171}
+ .util .acts a{margin-left:14px;color:#cfd4d9}.util .acts a.sub{color:#fff;background:var(--red);padding:4px 12px;border-radius:3px;font-weight:700}
+ .mast{border-bottom:2px solid var(--ink);padding:20px 0 14px}
+ .mast .wrap{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;gap:3px}
+ .logo{font-family:var(--serif);font-weight:700;font-size:34px;letter-spacing:-1px}.logo span{color:var(--red)}
+ .logo small{display:block;font-size:11px;font-weight:600;letter-spacing:3px;color:var(--sub);text-transform:uppercase;margin-top:2px;font-family:var(--sans)}
+ .datebox{font-size:12px;color:var(--sub);text-align:center}
+ nav{border-bottom:1px solid var(--line);position:sticky;top:0;background:#fff;z-index:10}
+ nav .wrap{display:flex;gap:2px;align-items:center;height:46px}
+ .ham{display:none;background:none;border:0;font-size:24px;line-height:1;color:var(--ink);cursor:pointer;padding:8px 12px 8px 0;margin-right:4px}
+ .navlinks{display:flex;gap:2px;align-items:center;overflow-x:auto}
+ nav a{font-size:13px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;padding:14px 13px;border-bottom:3px solid transparent;white-space:nowrap;cursor:pointer}
+ nav a:hover,nav a.on{color:var(--red);border-color:var(--red)}
+ @media(max-width:860px){
+ .ham{display:block;order:-1}
+ nav .wrap{height:52px}
+ .navlinks{display:none;position:absolute;top:52px;left:0;right:0;background:#fff;flex-direction:column;align-items:stretch;border-bottom:2px solid var(--ink);box-shadow:0 10px 24px rgba(0,0,0,.14);z-index:30;max-height:78vh;overflow-y:auto}
+ .navlinks.open{display:flex}
+ .navlinks a{padding:15px 20px;border-bottom:1px solid var(--line);border-left:4px solid transparent}
+ .navlinks a:hover,.navlinks a.on{color:var(--red);border-bottom:1px solid var(--line);border-left-color:var(--red)}
+ }
+ .phero{background:linear-gradient(135deg,#111827,#c8102e);color:#fff;padding:54px 0}
+ .phero .k{font-size:12px;letter-spacing:.22em;text-transform:uppercase;opacity:.85;margin-bottom:12px}
+ .phero h1{font-family:var(--serif);font-size:clamp(32px,5vw,52px);line-height:1.08;letter-spacing:-.5px;max-width:20ch}
+ .phero p{max-width:60ch;margin-top:14px;font-size:17px;opacity:.94}
+ .rv{opacity:0;transform:translateY(18px);transition:opacity .6s ease,transform .6s ease}.rv.in{opacity:1;transform:none}
+ @media(prefers-reduced-motion:reduce){.rv{transition:none;opacity:1;transform:none}}
+ section.blk{padding:52px 0;border-bottom:1px solid var(--line)}
+ .eyebrow{font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.14em;color:var(--red);margin-bottom:10px}
+ h2.big{font-family:var(--serif);font-size:clamp(26px,3.4vw,38px);line-height:1.12;letter-spacing:-.4px;max-width:24ch}
+ .lead2{max-width:66ch;color:var(--sub);margin-top:12px;font-size:18px}
+ .cols3{display:grid;grid-template-columns:repeat(3,1fr);gap:22px;margin-top:30px}
+ .cols2{display:grid;grid-template-columns:1fr 1fr;gap:22px;margin-top:30px}
+ @media(max-width:860px){.cols3{grid-template-columns:1fr}.cols2{grid-template-columns:1fr}}
+ .tile{border:1px solid var(--line);border-radius:8px;padding:26px 24px;transition:.25s;background:#fff}
+ .tile:hover{transform:translateY(-4px);box-shadow:0 18px 44px rgba(0,0,0,.09);border-color:#cfd4d9}
+ .tile .n{font-family:var(--serif);font-size:15px;color:var(--red)}
+ .tile h3{font-family:var(--serif);font-size:22px;margin:8px 0 8px}
+ .tile p{color:var(--sub);font-size:15px}
+ .tile .price{margin-top:14px;font-size:13px;font-weight:800;text-transform:uppercase;letter-spacing:.05em;color:var(--ink)}
+ .statrow{display:flex;flex-wrap:wrap;gap:44px;margin-top:26px}
+ .statrow .v{font-family:var(--serif);font-size:40px;color:var(--red);line-height:1}
+ .statrow .l{font-size:12px;letter-spacing:.06em;text-transform:uppercase;color:var(--sub);margin-top:6px}
+ .cta{display:inline-block;background:var(--red);color:#fff;font-weight:800;font-size:13px;text-transform:uppercase;letter-spacing:.06em;padding:13px 26px;border-radius:5px;cursor:pointer;border:0;margin-top:22px}
+ .cta.ghost{background:transparent;color:var(--ink);border:1.5px solid var(--ink)}
+ .cta:hover{filter:brightness(1.06)}
+ .form{max-width:520px;margin-top:26px}
+ .form label{display:block;font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--sub);margin:14px 0 6px}
+ .form input,.form select{width:100%;padding:12px 14px;border:1px solid var(--line);border-radius:5px;font-size:15px;font-family:inherit}
+ .form .ok{display:none;margin-top:14px;padding:12px 16px;background:#ecfdf3;border:1px solid #a7f3d0;border-radius:6px;color:#067647;font-size:14px}
+ .kv{display:flex;justify-content:space-between;padding:11px 0;border-bottom:1px solid var(--line);font-size:15px}.kv b{font-weight:700}
+ footer{background:var(--ink);color:#aeb6bd;margin-top:0;padding:40px 0 30px;font-size:13px}
+ footer .cols{display:grid;grid-template-columns:2fr 1fr 1fr 1fr;gap:28px}
+ footer .logo{color:#fff;font-size:26px;margin-bottom:8px}footer h5{color:#fff;font-size:12px;text-transform:uppercase;letter-spacing:.08em;margin-bottom:10px}footer a{display:block;padding:4px 0;color:#aeb6bd}
+ footer .fine{border-top:1px solid #2a2f34;margin-top:26px;padding-top:16px;font-size:12px;color:#7c848b}
+ @media(max-width:860px){footer .cols{grid-template-columns:1fr 1fr}}
+</style></head><body>
+
+ <div class="util"><div class="wrap">
+ <div class="ticker" id="ticker"><span><b>CRE INDEX</b> …</span><span><b>10-YR</b> …</span><span><b>LA OFFICE VAC</b> …</span></div>
+ <div class="acts"><a href="/subscribe">Newsletters</a><a href="/advertise">Advertise</a><a href="/subscribe" class="sub">Subscribe</a></div>
+ </div></div>
+ <header class="mast"><div class="wrap">
+ <a class="logo" href="/">REN<span>TV</span>.com<small>Commercial Real Estate News</small></a>
+ <div class="datebox"><span>Western U.S. Edition</span><br><span id="today"></span></div>
+ </div></header>
+ <nav><div class="wrap">
+ <button class="ham" id="hamBtn" aria-label="Menu" aria-expanded="false">☰</button>
+ <div class="navlinks" id="nav">
+ <a href="/">Home</a><a href="/sales">Sales</a><a href="/leases">Leases</a><a href="/financing">Financing</a><a href="/development">Development</a><a href="/multifamily">Multifamily</a><a href="/industrial">Industrial</a><a href="/retail">Retail</a><a href="/review">The REview</a><a href="/conferences" class="on">Conferences</a>
+ </div>
+ </div></nav>
+
+ <div class="phero"><div class="wrap">
+ <div class="k">RENTV Conferences · since 1998</div>
+ <h1>The State of the Market Summit</h1>
+ <p>Where the Western-U.S. commercial real estate community meets — brokers, investors, developers and lenders, live, twice a year. The conference franchise behind RENTV.</p>
+ </div></div>
+ <section class="blk"><div class="wrap">
+ <div class="statrow rv">
+ <div><div class="v">600+</div><div class="l">CRE decision-makers per summit</div></div>
+ <div><div class="v">2×</div><div class="l">Flagship summits a year</div></div>
+ <div><div class="v">25+</div><div class="l">Years convening the market</div></div>
+ <div><div class="v">$175</div><div class="l">Standard delegate pass</div></div>
+ </div>
+ </div></section>
+ <section class="blk"><div class="wrap">
+ <div class="eyebrow rv">Upcoming</div><h2 class="big rv">Two rooms the whole market shows up for.</h2>
+ <div class="cols2">
+ <div class="tile rv"><div class="n">Fall 2026</div><h3>State of the Market — Los Angeles</h3><p>The flagship. Capital-markets outlook, office repositioning, industrial & multifamily deal flow, and the networking that actually closes deals.</p><div class="price">Delegate $175 · Sponsor packages available</div><a class="cta" href="/subscribe">Get date + registration alerts →</a></div>
+ <div class="tile rv"><div class="n">Spring 2027</div><h3>Capital & Development Forum</h3><p>The build-and-finance half of the calendar — construction lending, entitlements, and the projects breaking ground across the West.</p><div class="price">Delegate $175 · Sponsor packages available</div><a class="cta ghost" href="/advertise">Become a sponsor →</a></div>
+ </div>
+ </div></section>
+ <section class="blk"><div class="wrap">
+ <div class="eyebrow rv">Why sponsor</div><h2 class="big rv">Put your firm in front of the room that moves the market.</h2>
+ <p class="lead2 rv">Conference sponsorship pairs naturally with RENTV's newsletter and site audience — the same decision-makers, reached before, during, and after the event. Ask about integrated packages that bundle the summit with sponsored content and newsletter placement.</p>
+ <a class="cta rv" href="/advertise">Request the sponsor kit →</a>
+ </div></section>
+
+ <footer><div class="wrap"><div class="cols">
+ <div><div class="logo">REN<span style="color:var(--red)">TV</span>.com</div><p style="max-width:34ch">Commercial real estate news, deals & conferences across the Western United States since 1998.</p></div>
+ <div><h5>Sections</h5><a href="/sales">Sales</a><a href="/leases">Leases</a><a href="/financing">Financing</a><a href="/development">Development</a></div>
+ <div><h5>Company</h5><a href="/about">About</a><a href="/advertise">Advertise</a><a href="/conferences">Conferences</a><a href="/subscribe">Subscribe</a></div>
+ <div><h5>Follow</h5><a href="https://www.linkedin.com/company/rentv.com-inc" target="_blank" rel="noopener">LinkedIn</a><a href="/review">The REview</a><a href="/subscribe">Newsletters</a></div>
+ </div><div class="fine">© 2026 RENTV.com · 5757 W. Century Blvd, Suite 700, Los Angeles, CA 90045 · (310) 213-6409</div></div></footer>
+<script>
+ var t=document.getElementById('today');if(t)t.textContent=new Date().toLocaleDateString(undefined,{weekday:'long',year:'numeric',month:'long',day:'numeric'});
+ var hb=document.getElementById('hamBtn');if(hb)hb.addEventListener('click',function(){var o=document.getElementById('nav').classList.toggle('open');hb.setAttribute('aria-expanded',o);});
+ var esc=function(s){return (s||'').replace(/[&<>"]/g,function(c){return {'&':'&','<':'<','>':'>','"':'"'}[c];});};
+ (function(){fetch('/api/ticker').then(function(r){return r.json();}).then(function(t){
+ function cell(m){if(!m||!m.value)return '';var amt=m.change_pct!=null?Math.abs(m.change_pct)+'%':(m.change_bps!=null?Math.abs(m.change_bps)+'bps':'');var arr=m.dir==='up'?' <span class="up">▲'+amt+'</span>':(m.dir==='down'?' <span class="dn">▼'+amt+'</span>':'');return '<span><b>'+esc(m.label)+'</b> '+esc(m.value)+arr+'</span>';}
+ var h=[t.cre_index,t.ten_yr,t.la_office_vac,t.ie_industrial_cap].map(cell).filter(Boolean).join('');
+ var el=document.getElementById('ticker');if(h&&el)el.innerHTML=h;
+ }).catch(function(){});})();
+ var io=new IntersectionObserver(function(es){es.forEach(function(e){if(e.isIntersecting){e.target.classList.add('in');io.unobserve(e.target);}});},{threshold:.1});
+ document.querySelectorAll('.rv').forEach(function(el){io.observe(el);});
+ document.querySelectorAll('form[data-fakepost]').forEach(function(f){f.addEventListener('submit',function(e){e.preventDefault();var ok=f.querySelector('.ok');if(ok){ok.style.display='block';}f.querySelectorAll('input,select,button').forEach(function(x){if(x.type!=='reset')x.setAttribute('disabled','');});});});</script>
+</body></html>
\ No newline at end of file
diff --git a/public/index.html b/public/index.html
index b405db1..37e2c77 100644
--- a/public/index.html
+++ b/public/index.html
@@ -84,7 +84,7 @@
<body>
<div class="util"><div class="wrap">
<div class="ticker" id="ticker"><span><b>CRE INDEX</b> …</span><span><b>10-YR</b> …</span><span><b>LA OFFICE VAC</b> …</span><span><b>IE INDUSTRIAL CAP</b> …</span></div>
- <div class="acts"><a href="#">Newsletters</a><a href="#">Advertise</a><a href="#">Log In</a><a class="sub" href="#news">Subscribe</a></div>
+ <div class="acts"><a href="/subscribe">Newsletters</a><a href="/advertise">Advertise</a><a class="sub" href="/subscribe">Subscribe</a></div>
</div></div>
<header class="mast"><div class="wrap">
@@ -95,7 +95,7 @@
<nav><div class="wrap">
<button class="ham" id="hamBtn" aria-label="Menu" aria-expanded="false">☰</button>
<div class="navlinks" id="nav">
- <a data-cat="all" class="on">Home</a><a data-cat="Sales">Sales</a><a data-cat="Leases">Leases</a><a data-cat="Financing">Financing</a><a data-cat="Development">Development</a><a data-cat="Multifamily">Multifamily</a><a data-cat="Industrial">Industrial</a><a data-cat="Retail">Retail</a><a href="/review">The REview</a><a href="#conf">Conferences</a>
+ <a data-cat="all" class="on">Home</a><a data-cat="Sales">Sales</a><a data-cat="Leases">Leases</a><a data-cat="Financing">Financing</a><a data-cat="Development">Development</a><a data-cat="Multifamily">Multifamily</a><a data-cat="Industrial">Industrial</a><a data-cat="Retail">Retail</a><a href="/review">The REview</a><a href="/conferences">Conferences</a>
</div>
</div></nav>
@@ -112,7 +112,7 @@
<aside class="rail">
<div class="ns box"><h3>The RENTV Daily</h3><p>Western-U.S. commercial real estate deals in your inbox every morning — free.</p><input id="email" placeholder="you@company.com"><button id="subbtn">Subscribe free</button><div class="ok" id="subok">✓ You're on the list.</div></div>
<div><div class="sechead" style="margin-top:0"><h2>Most Read</h2></div><ol class="mostread" id="mostread"></ol></div>
- <div class="conf" id="conf"><div class="k">RENTV Conferences</div><h3>State of the Market Summit</h3><p style="font-size:13px;opacity:.9">600+ brokers, investors & developers · Los Angeles.</p><a href="#">Register →</a></div>
+ <div class="conf" id="conf"><div class="k">RENTV Conferences</div><h3>State of the Market Summit</h3><p style="font-size:13px;opacity:.9">600+ brokers, investors & developers · Los Angeles.</p><a href="/conferences">Register →</a></div>
<div class="box"><div class="sechead" style="margin-top:0"><h2>Market Snapshot</h2></div>
<div style="display:flex;justify-content:space-between;padding:7px 0;border-bottom:1px solid var(--line);font-size:13px"><span>LA Office Vacancy</span><b>23.1%</b></div>
<div style="display:flex;justify-content:space-between;padding:7px 0;border-bottom:1px solid var(--line);font-size:13px"><span>IE Industrial Cap</span><b>5.2%</b></div>
@@ -123,9 +123,9 @@
<footer><div class="wrap"><div class="cols">
<div><div class="logo">REN<span style="color:var(--red)">TV</span>.com</div><p style="max-width:34ch">Commercial real estate news, deals & conferences across the Western United States since 1998.</p></div>
- <div><h5>Sections</h5><a href="#">Deals</a><a href="#">Sales</a><a href="#">Leases</a><a href="#">Financing</a></div>
- <div><h5>Company</h5><a href="#">About</a><a href="#">Advertise</a><a href="#">Conferences</a><a href="#">Contact</a></div>
- <div><h5>Follow</h5><a href="#">LinkedIn</a><a href="#">X / Twitter</a><a href="#">Newsletters</a></div>
+ <div><h5>Sections</h5><a href="/sales">Sales</a><a href="/leases">Leases</a><a href="/financing">Financing</a><a href="/development">Development</a></div>
+ <div><h5>Company</h5><a href="/about">About</a><a href="/advertise">Advertise</a><a href="/conferences">Conferences</a><a href="/subscribe">Subscribe</a></div>
+ <div><h5>Follow</h5><a href="https://www.linkedin.com/company/rentv.com-inc" target="_blank" rel="noopener">LinkedIn</a><a href="/review">The REview</a><a href="/subscribe">Newsletters</a></div>
</div><div class="fine">© 2026 RENTV.com · Headlines refreshed live from rentv.com · <span id="src"></span></div></div></footer>
<script>
diff --git a/public/subscribe.html b/public/subscribe.html
new file mode 100644
index 0000000..128af9b
--- /dev/null
+++ b/public/subscribe.html
@@ -0,0 +1,137 @@
+<!doctype html>
+<html lang="en"><head>
+<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
+<title>Subscribe — RENTV.com</title>
+<meta name="description" content="Get the free RENTV Daily — Western-U.S. commercial real estate deals, leases and financings in your inbox every morning.">
+<link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,700;1,400&family=Inter:wght@300;400;600;800&display=swap" rel="stylesheet">
+<style>
+ :root{--red:#c8102e;--ink:#14171a;--sub:#5b636b;--line:#e4e7ea;--bg:#fff;--wash:#f5f6f8;--sans:'Inter',system-ui,sans-serif;--serif:'Playfair Display',Georgia,serif}
+ *{box-sizing:border-box;margin:0;padding:0}
+ body{font-family:var(--sans);color:var(--ink);background:var(--bg);line-height:1.5}
+ a{color:inherit;text-decoration:none}
+ .wrap{max-width:1200px;margin:0 auto;padding:0 20px}
+ .util{background:var(--ink);color:#cfd4d9;font-size:12px}
+ .util .wrap{display:flex;justify-content:space-between;align-items:center;height:34px}
+ .ticker{display:flex;gap:20px;overflow:hidden;white-space:nowrap}.ticker b{color:#fff}.up{color:#4ade80}.dn{color:#f87171}
+ .util .acts a{margin-left:14px;color:#cfd4d9}.util .acts a.sub{color:#fff;background:var(--red);padding:4px 12px;border-radius:3px;font-weight:700}
+ .mast{border-bottom:2px solid var(--ink);padding:20px 0 14px}
+ .mast .wrap{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;gap:3px}
+ .logo{font-family:var(--serif);font-weight:700;font-size:34px;letter-spacing:-1px}.logo span{color:var(--red)}
+ .logo small{display:block;font-size:11px;font-weight:600;letter-spacing:3px;color:var(--sub);text-transform:uppercase;margin-top:2px;font-family:var(--sans)}
+ .datebox{font-size:12px;color:var(--sub);text-align:center}
+ nav{border-bottom:1px solid var(--line);position:sticky;top:0;background:#fff;z-index:10}
+ nav .wrap{display:flex;gap:2px;align-items:center;height:46px}
+ .ham{display:none;background:none;border:0;font-size:24px;line-height:1;color:var(--ink);cursor:pointer;padding:8px 12px 8px 0;margin-right:4px}
+ .navlinks{display:flex;gap:2px;align-items:center;overflow-x:auto}
+ nav a{font-size:13px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;padding:14px 13px;border-bottom:3px solid transparent;white-space:nowrap;cursor:pointer}
+ nav a:hover,nav a.on{color:var(--red);border-color:var(--red)}
+ @media(max-width:860px){
+ .ham{display:block;order:-1}
+ nav .wrap{height:52px}
+ .navlinks{display:none;position:absolute;top:52px;left:0;right:0;background:#fff;flex-direction:column;align-items:stretch;border-bottom:2px solid var(--ink);box-shadow:0 10px 24px rgba(0,0,0,.14);z-index:30;max-height:78vh;overflow-y:auto}
+ .navlinks.open{display:flex}
+ .navlinks a{padding:15px 20px;border-bottom:1px solid var(--line);border-left:4px solid transparent}
+ .navlinks a:hover,.navlinks a.on{color:var(--red);border-bottom:1px solid var(--line);border-left-color:var(--red)}
+ }
+ .phero{background:linear-gradient(135deg,#111827,#c8102e);color:#fff;padding:54px 0}
+ .phero .k{font-size:12px;letter-spacing:.22em;text-transform:uppercase;opacity:.85;margin-bottom:12px}
+ .phero h1{font-family:var(--serif);font-size:clamp(32px,5vw,52px);line-height:1.08;letter-spacing:-.5px;max-width:20ch}
+ .phero p{max-width:60ch;margin-top:14px;font-size:17px;opacity:.94}
+ .rv{opacity:0;transform:translateY(18px);transition:opacity .6s ease,transform .6s ease}.rv.in{opacity:1;transform:none}
+ @media(prefers-reduced-motion:reduce){.rv{transition:none;opacity:1;transform:none}}
+ section.blk{padding:52px 0;border-bottom:1px solid var(--line)}
+ .eyebrow{font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.14em;color:var(--red);margin-bottom:10px}
+ h2.big{font-family:var(--serif);font-size:clamp(26px,3.4vw,38px);line-height:1.12;letter-spacing:-.4px;max-width:24ch}
+ .lead2{max-width:66ch;color:var(--sub);margin-top:12px;font-size:18px}
+ .cols3{display:grid;grid-template-columns:repeat(3,1fr);gap:22px;margin-top:30px}
+ .cols2{display:grid;grid-template-columns:1fr 1fr;gap:22px;margin-top:30px}
+ @media(max-width:860px){.cols3{grid-template-columns:1fr}.cols2{grid-template-columns:1fr}}
+ .tile{border:1px solid var(--line);border-radius:8px;padding:26px 24px;transition:.25s;background:#fff}
+ .tile:hover{transform:translateY(-4px);box-shadow:0 18px 44px rgba(0,0,0,.09);border-color:#cfd4d9}
+ .tile .n{font-family:var(--serif);font-size:15px;color:var(--red)}
+ .tile h3{font-family:var(--serif);font-size:22px;margin:8px 0 8px}
+ .tile p{color:var(--sub);font-size:15px}
+ .tile .price{margin-top:14px;font-size:13px;font-weight:800;text-transform:uppercase;letter-spacing:.05em;color:var(--ink)}
+ .statrow{display:flex;flex-wrap:wrap;gap:44px;margin-top:26px}
+ .statrow .v{font-family:var(--serif);font-size:40px;color:var(--red);line-height:1}
+ .statrow .l{font-size:12px;letter-spacing:.06em;text-transform:uppercase;color:var(--sub);margin-top:6px}
+ .cta{display:inline-block;background:var(--red);color:#fff;font-weight:800;font-size:13px;text-transform:uppercase;letter-spacing:.06em;padding:13px 26px;border-radius:5px;cursor:pointer;border:0;margin-top:22px}
+ .cta.ghost{background:transparent;color:var(--ink);border:1.5px solid var(--ink)}
+ .cta:hover{filter:brightness(1.06)}
+ .form{max-width:520px;margin-top:26px}
+ .form label{display:block;font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--sub);margin:14px 0 6px}
+ .form input,.form select{width:100%;padding:12px 14px;border:1px solid var(--line);border-radius:5px;font-size:15px;font-family:inherit}
+ .form .ok{display:none;margin-top:14px;padding:12px 16px;background:#ecfdf3;border:1px solid #a7f3d0;border-radius:6px;color:#067647;font-size:14px}
+ .kv{display:flex;justify-content:space-between;padding:11px 0;border-bottom:1px solid var(--line);font-size:15px}.kv b{font-weight:700}
+ footer{background:var(--ink);color:#aeb6bd;margin-top:0;padding:40px 0 30px;font-size:13px}
+ footer .cols{display:grid;grid-template-columns:2fr 1fr 1fr 1fr;gap:28px}
+ footer .logo{color:#fff;font-size:26px;margin-bottom:8px}footer h5{color:#fff;font-size:12px;text-transform:uppercase;letter-spacing:.08em;margin-bottom:10px}footer a{display:block;padding:4px 0;color:#aeb6bd}
+ footer .fine{border-top:1px solid #2a2f34;margin-top:26px;padding-top:16px;font-size:12px;color:#7c848b}
+ @media(max-width:860px){footer .cols{grid-template-columns:1fr 1fr}}
+</style></head><body>
+
+ <div class="util"><div class="wrap">
+ <div class="ticker" id="ticker"><span><b>CRE INDEX</b> …</span><span><b>10-YR</b> …</span><span><b>LA OFFICE VAC</b> …</span></div>
+ <div class="acts"><a href="/subscribe">Newsletters</a><a href="/advertise">Advertise</a><a href="/subscribe" class="sub">Subscribe</a></div>
+ </div></div>
+ <header class="mast"><div class="wrap">
+ <a class="logo" href="/">REN<span>TV</span>.com<small>Commercial Real Estate News</small></a>
+ <div class="datebox"><span>Western U.S. Edition</span><br><span id="today"></span></div>
+ </div></header>
+ <nav><div class="wrap">
+ <button class="ham" id="hamBtn" aria-label="Menu" aria-expanded="false">☰</button>
+ <div class="navlinks" id="nav">
+ <a href="/">Home</a><a href="/sales">Sales</a><a href="/leases">Leases</a><a href="/financing">Financing</a><a href="/development">Development</a><a href="/multifamily">Multifamily</a><a href="/industrial">Industrial</a><a href="/retail">Retail</a><a href="/review">The REview</a><a href="/conferences">Conferences</a>
+ </div>
+ </div></nav>
+
+ <div class="phero"><div class="wrap">
+ <div class="k">Free · Every weekday morning</div>
+ <h1>The RENTV Daily.</h1>
+ <p>Every Western-U.S. commercial real estate deal, lease and financing that matters — summarized and in your inbox before your first meeting. Free, since 1998.</p>
+ </div></div>
+ <section class="blk"><div class="wrap">
+ <div class="cols2">
+ <div class="rv">
+ <div class="eyebrow">What you get</div><h2 class="big">Written for people who close deals.</h2>
+ <div style="margin-top:22px">
+ <div class="kv"><span>The RENTV Daily</span><b>Every weekday · free</b></div>
+ <div class="kv"><span>Deal Alerts (Sales · Leases · Financing)</span><b>As they break</b></div>
+ <div class="kv"><span>Conference & event notices</span><b>Occasional</b></div>
+ <div class="kv"><span>The REview video digest</span><b>Weekly</b></div>
+ </div>
+ <p class="lead2" style="margin-top:20px">No spam, ever. One-click unsubscribe. Your address is never sold.</p>
+ </div>
+ <div class="tile rv" style="align-self:start">
+ <div class="n">Join free</div><h3>Start getting the Daily</h3>
+ <form class="form" data-fakepost style="margin-top:8px">
+ <label>Work email</label><input type="email" required placeholder="you@company.com">
+ <label>First name</label><input placeholder="First name">
+ <label>Primary interest</label><select><option>All Western-U.S. CRE</option><option>Sales</option><option>Leases</option><option>Financing</option><option>Development</option><option>Multifamily</option><option>Industrial</option><option>Retail</option></select>
+ <button class="cta" type="submit">Subscribe free →</button>
+ <div class="ok">✓ You're on the list. Watch for tomorrow's RENTV Daily.</div>
+ </form>
+ </div>
+ </div>
+ </div></section>
+
+ <footer><div class="wrap"><div class="cols">
+ <div><div class="logo">REN<span style="color:var(--red)">TV</span>.com</div><p style="max-width:34ch">Commercial real estate news, deals & conferences across the Western United States since 1998.</p></div>
+ <div><h5>Sections</h5><a href="/sales">Sales</a><a href="/leases">Leases</a><a href="/financing">Financing</a><a href="/development">Development</a></div>
+ <div><h5>Company</h5><a href="/about">About</a><a href="/advertise">Advertise</a><a href="/conferences">Conferences</a><a href="/subscribe">Subscribe</a></div>
+ <div><h5>Follow</h5><a href="https://www.linkedin.com/company/rentv.com-inc" target="_blank" rel="noopener">LinkedIn</a><a href="/review">The REview</a><a href="/subscribe">Newsletters</a></div>
+ </div><div class="fine">© 2026 RENTV.com · 5757 W. Century Blvd, Suite 700, Los Angeles, CA 90045 · (310) 213-6409</div></div></footer>
+<script>
+ var t=document.getElementById('today');if(t)t.textContent=new Date().toLocaleDateString(undefined,{weekday:'long',year:'numeric',month:'long',day:'numeric'});
+ var hb=document.getElementById('hamBtn');if(hb)hb.addEventListener('click',function(){var o=document.getElementById('nav').classList.toggle('open');hb.setAttribute('aria-expanded',o);});
+ var esc=function(s){return (s||'').replace(/[&<>"]/g,function(c){return {'&':'&','<':'<','>':'>','"':'"'}[c];});};
+ (function(){fetch('/api/ticker').then(function(r){return r.json();}).then(function(t){
+ function cell(m){if(!m||!m.value)return '';var amt=m.change_pct!=null?Math.abs(m.change_pct)+'%':(m.change_bps!=null?Math.abs(m.change_bps)+'bps':'');var arr=m.dir==='up'?' <span class="up">▲'+amt+'</span>':(m.dir==='down'?' <span class="dn">▼'+amt+'</span>':'');return '<span><b>'+esc(m.label)+'</b> '+esc(m.value)+arr+'</span>';}
+ var h=[t.cre_index,t.ten_yr,t.la_office_vac,t.ie_industrial_cap].map(cell).filter(Boolean).join('');
+ var el=document.getElementById('ticker');if(h&&el)el.innerHTML=h;
+ }).catch(function(){});})();
+ var io=new IntersectionObserver(function(es){es.forEach(function(e){if(e.isIntersecting){e.target.classList.add('in');io.unobserve(e.target);}});},{threshold:.1});
+ document.querySelectorAll('.rv').forEach(function(el){io.observe(el);});
+ document.querySelectorAll('form[data-fakepost]').forEach(function(f){f.addEventListener('submit',function(e){e.preventDefault();var ok=f.querySelector('.ok');if(ok){ok.style.display='block';}f.querySelectorAll('input,select,button').forEach(function(x){if(x.type!=='reset')x.setAttribute('disabled','');});});});</script>
+</body></html>
\ No newline at end of file
diff --git a/server.js b/server.js
index 4e2ac35..2e3c943 100644
--- a/server.js
+++ b/server.js
@@ -17,6 +17,7 @@ const CREDS = ['admin:DW2024!', 'Boomer:Rentv2024!']
const ACCEPTED = new Set(CREDS.map(c => 'Basic ' + Buffer.from(c).toString('base64')));
app.get('/api/health', (_q, r) => r.json({ ok: true, at: new Date().toISOString() }));
app.use((req, res, next) => {
+ if (process.env.OPEN === '1') return next(); // local-preview bypass only; prod never sets OPEN
if (ACCEPTED.has(req.headers.authorization || '')) return next();
res.set('WWW-Authenticate', 'Basic realm="RENTV"');
return res.status(401).send('Authentication required');
@@ -40,6 +41,12 @@ app.get('/api/videos', (_q, r) => {
r.json(readJSON('videos.json', { items: [], cats: [] }));
});
+// ── Markets: CRE market fundamentals + snapshot (refreshed by pull-markets cron) ──
+app.get('/api/markets', (_q, r) => {
+ r.set('Cache-Control', 'public, max-age=300');
+ r.json(readJSON('markets.json', {}));
+});
+
// ── Article reader proxy: fetch a single rentv.com story on demand + cache it. ──
const artCache = new Map(); // id -> { at, data }
const ART_TTL = 15 * 60 * 1000;
← 71dae0e auto-save: 2026-07-21T12:37:29 (3 files) — data/markets.json
·
back to Rentv V1
·
auto-save: 2026-07-21T13:07:37 (3 files) — data/markets.json 6abac16 →