← back to Rentv
build.mjs
334 lines
#!/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:42px;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:13px 8px;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;margin-left:auto}
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'], ['/markets', 'Markets'], ['/review', 'The REview'], ['/cre-talk', 'CRE Talk'], ['/conferences', 'Conferences'], ['/versions', 'Versions'], ['/blog', 'Blog']];
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><a href="/multifamily">Multifamily</a><a href="/industrial">Industrial</a><a href="/retail">Retail</a><a href="/markets">Markets</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="/cre-talk">CRE Talk</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','');});});});
// Real newsletter capture → POST /api/subscribe (append-only JSONL; no external send-to-list).
document.querySelectorAll('form[data-subscribe]').forEach(function(f){f.addEventListener('submit',function(e){e.preventDefault();
var email=(f.querySelector('input[type=email]')||{}).value||'';
var name=(f.querySelector('input[data-name]')||{}).value||'';
var interest=(f.querySelector('select')||{}).value||'';
var ok=f.querySelector('.ok');var btn=f.querySelector('button');if(btn)btn.setAttribute('disabled','');
fetch('/api/subscribe',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({email:email,name:name,interest:interest,source:f.getAttribute('data-subscribe')||'site'})})
.then(function(r){return r.json();}).then(function(j){
if(j&&j.ok){if(ok){ok.style.display='block';}f.querySelectorAll('input,select').forEach(function(x){x.setAttribute('disabled','');});}
else{if(btn)btn.removeAttribute('disabled');alert((j&&j.error)?('Please enter a valid email — '+j.error):'Could not subscribe, please try again.');}
}).catch(function(){if(btn)btn.removeAttribute('disabled');alert('Network error — please try again.');});
});});`;
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>
<script src="/theme.js"></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-subscribe="subscribe-page" style="margin-top:8px">
<label>Work email</label><input type="email" required placeholder="you@company.com">
<label>First name</label><input data-name 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>`);
// ── CRE Talk (the interview series; surfaces the REAL video catalog live) ──
const creTalk = page('CRE Talk', 'CRE Talk — RENTV\'s interview series with the CEOs and principals steering Western-U.S. commercial real estate.', '/cre-talk', `
<div class="phero"><div class="wrap">
<div class="k">The Interview Series</div>
<h1>CRE Talk.</h1>
<p>Candid, on-the-record conversations with the CEOs, principals and dealmakers steering Western-U.S. commercial real estate — where the market's really headed, from the people moving it.</p>
</div></div>
<section class="blk"><div class="wrap">
<div class="cols3 rv">
<div class="tile"><div class="n">Format</div><h3>15–25 minutes</h3><p>One leader, one host, no fluff — the strategy conversation you'd want over coffee, on the record.</p></div>
<div class="tile"><div class="n">Guests</div><h3>Regional principals</h3><p>The CEOs and heads of capital markets, development and brokerage across the West.</p></div>
<div class="tile"><div class="n">Where</div><h3>On The REview</h3><p>Every episode lives on RENTV's video platform — watch, share, and subscribe for new drops.</p></div>
</div>
</div></section>
<section class="blk"><div class="wrap">
<div class="eyebrow rv">Watch</div><h2 class="big rv">From The REview.</h2>
<p class="lead2 rv">CRE Talk episodes live on The REview, alongside RENTV's full video catalog — market panels, property features and deal breakdowns. Here's what's fresh right now.</p>
<div class="cols3" id="vidgrid" style="margin-top:26px"><p style="color:var(--sub)">Loading the latest videos…</p></div>
<a class="cta rv" href="/review" style="margin-top:26px">See the full REview catalog →</a>
</div></section>
<section class="blk"><div class="wrap">
<div class="cols2">
<div class="tile rv"><div class="n">Be a guest</div><h3>Have a market view worth 20 minutes?</h3><p>We're always booking principals with something to say about where Western-U.S. CRE is going. Tell us about you.</p>
<form class="form" data-fakepost style="margin-top:8px"><label>Name & firm</label><input required placeholder="Name — Firm"><label>Email</label><input type="email" required placeholder="you@company.com"><button class="cta" type="submit">Pitch a segment →</button><div class="ok">✓ Thanks — our producers will be in touch.</div></form>
</div>
<div class="tile rv"><div class="n">Sponsor the series</div><h3>Put your brand on the conversation.</h3><p>Named sponsorship and pre-roll on CRE Talk reaches the exact decision-makers you want — before, during and after each episode.</p><a class="cta ghost" href="/advertise" style="margin-top:16px">See sponsor options →</a></div>
</div>
</div></section>
<script>
(function(){var g=document.getElementById('vidgrid');if(!g)return;
fetch('/api/videos').then(function(r){return r.json();}).then(function(d){
var items=(d.items||[]).slice(0,6);
if(!items.length){g.innerHTML='<p style="color:var(--sub)">Video catalog is refreshing — check back shortly.</p>';return;}
g.innerHTML=items.map(function(v){
var href=v.view_url||('https://www.rentvreview.com/Videos/View/'+encodeURIComponent(v.id||''));
var thumb=v.thumb||(v.yt?('https://img.youtube.com/vi/'+v.yt+'/hqdefault.jpg'):'');
return '<a class="tile" href="'+esc(href)+'" target="_blank" rel="noopener" style="padding:0;overflow:hidden">'+
'<div style="aspect-ratio:16/9;background:#111 center/cover'+(thumb?(" url('"+esc(thumb)+"')"):'')+'"></div>'+
'<div style="padding:16px 18px"><div class="n" style="font-size:11px;letter-spacing:.1em;text-transform:uppercase">'+esc(v.cat||'The REview')+'</div>'+
'<h3 style="font-size:18px;margin:6px 0 0">'+esc(v.title||'RENTV video')+'</h3></div></a>';
}).join('');
}).catch(function(){g.innerHTML='<p style="color:var(--sub)">Video catalog temporarily unavailable.</p>';});
})();
</script>`);
const pages = { 'conferences.html': conferences, 'advertise.html': advertise, 'subscribe.html': subscribe, 'about.html': about, 'cre-talk.html': creTalk };
for (const [f, html] of Object.entries(pages)) writeFileSync(join(OUT, f), html);
console.log('Wrote company pages: ' + Object.keys(pages).join(', '));