[object Object]

← back to Rentv

feat(services): guarantee >=1 vendor per category — curated Featured layer

8d4a638e63a0a7bd4987bbb6e2e07de9bd342de7 · 2026-08-06 12:10:32 -0700 · Steve

Every service category now shows at least one vendor in every metro. The public
license registries don't cover Title or Property Management and barely cover Legal
(3 attorney rows statewide), so those are filled by a curated seed of REAL, verifiable
major CRE firms (First American Title, CBRE, Allen Matkins, etc.), clearly badged
★ Featured and pinned above the registry rows — never fabricated data.

- data/services-featured.json: curated real firms (Title/Property/Legal + a flagship
  for each registry category), markets:'all' = serves all SoCal metros.
- server.js: Title + Property Management categories (role:null, featured-only);
  featuredFor() helper; /api/services pins featured on page 1 (skipped when a city
  filter is active); facets fold featured into per-cat counts so none render empty.
- services.html: gold ★ Featured pill + card treatment, featured pinned above rows,
  meta shows 'N featured', note explains the curation.
- build-services-content.mjs + services-content.json: blurbs for Title + Property (local Ollama, $0).

Files touched

Diff

commit 8d4a638e63a0a7bd4987bbb6e2e07de9bd342de7
Author: Steve <steve@designerwallcoverings.com>
Date:   Thu Aug 6 12:10:32 2026 -0700

    feat(services): guarantee >=1 vendor per category — curated Featured layer
    
    Every service category now shows at least one vendor in every metro. The public
    license registries don't cover Title or Property Management and barely cover Legal
    (3 attorney rows statewide), so those are filled by a curated seed of REAL, verifiable
    major CRE firms (First American Title, CBRE, Allen Matkins, etc.), clearly badged
    ★ Featured and pinned above the registry rows — never fabricated data.
    
    - data/services-featured.json: curated real firms (Title/Property/Legal + a flagship
      for each registry category), markets:'all' = serves all SoCal metros.
    - server.js: Title + Property Management categories (role:null, featured-only);
      featuredFor() helper; /api/services pins featured on page 1 (skipped when a city
      filter is active); facets fold featured into per-cat counts so none render empty.
    - services.html: gold ★ Featured pill + card treatment, featured pinned above rows,
      meta shows 'N featured', note explains the curation.
    - build-services-content.mjs + services-content.json: blurbs for Title + Property (local Ollama, $0).
---
 data/services-content.json         | 16 +++++++--
 data/services-featured.json        | 23 +++++++++++++
 public/services.html               | 21 ++++++++----
 scripts/build-services-content.mjs |  4 +++
 server.js                          | 67 ++++++++++++++++++++++++++++++++++----
 5 files changed, 115 insertions(+), 16 deletions(-)

diff --git a/data/services-content.json b/data/services-content.json
index 441905bc..9c56eab1 100644
--- a/data/services-content.json
+++ b/data/services-content.json
@@ -1,5 +1,5 @@
 {
-  "generated_at": "2026-08-06T17:45:03.913Z",
+  "generated_at": "2026-08-06T19:08:28.797Z",
   "model": "qwen2.5:latest",
   "market": "Greater LA",
   "intro": {
@@ -21,17 +21,27 @@
     "escrow": {
       "label": "Escrow",
       "role": "Escrow",
-      "blurb": "Escrow companies hold funds and documents until all conditions of a commercial real estate transaction are met."
+      "blurb": "Escrow companies hold funds and documents until all conditions of a commercial real estate deal are met."
     },
     "developers": {
       "label": "Developers",
       "role": "Developer",
-      "blurb": "Developers acquire, plan, and construct commercial properties for investment or lease."
+      "blurb": "Developers acquire, renovate, and lease commercial properties."
     },
     "legal": {
       "label": "Legal",
       "role": "Attorney",
       "blurb": "Legal professionals ensure compliance and protect interests in commercial real estate transactions."
+    },
+    "title": {
+      "label": "Title",
+      "role": null,
+      "blurb": "Title insurance and closing companies ensure legal ownership and facilitate transactions in commercial real estate."
+    },
+    "property": {
+      "label": "Property Management",
+      "role": null,
+      "blurb": "Manage properties, ensure tenant compliance, maintain assets, and maximize income for commercial real estate."
     }
   }
 }
\ No newline at end of file
diff --git a/data/services-featured.json b/data/services-featured.json
new file mode 100644
index 00000000..b4670761
--- /dev/null
+++ b/data/services-featured.json
@@ -0,0 +1,23 @@
+{
+  "note": "Editorially FEATURED, real and verifiable major CRE service firms. Purpose: guarantee at least one vendor in EVERY service category in EVERY served metro, including the categories the public California license registries do not cover (Title, Property Management) or barely cover (Legal — only 3 attorney records exist statewide in the registry). These are well-known firms that genuinely serve Southern California commercial real estate; markets:\"all\" means they operate across all served metros (Greater LA, Orange County, San Diego, Inland Empire, Ventura). Registry-backed categories (Construction, Lenders, Escrow, Developers) already have hundreds-to-thousands of vendors per metro and need no featured seed. Verify engagement terms and current licensure directly with each firm.",
+  "vendors": [
+    { "cat": "title", "name": "First American Title", "website": "https://www.firstam.com", "hq": "Santa Ana, CA", "markets": "all", "desc": "National title insurance, commercial title & settlement services." },
+    { "cat": "title", "name": "Fidelity National Title", "website": "https://www.fntic.com", "hq": "Los Angeles, CA", "markets": "all", "desc": "Commercial title insurance and closing services across California." },
+    { "cat": "title", "name": "Chicago Title", "website": "https://www.chicagotitle.com", "hq": "Los Angeles, CA", "markets": "all", "desc": "Commercial title & escrow (a Fidelity National Financial company)." },
+    { "cat": "title", "name": "Old Republic Title", "website": "https://www.oldrepublictitle.com", "hq": "Los Angeles, CA", "markets": "all", "desc": "National underwriter of commercial title insurance." },
+
+    { "cat": "property", "name": "CBRE", "website": "https://www.cbre.com", "hq": "Los Angeles, CA", "markets": "all", "desc": "Global commercial property & facilities management." },
+    { "cat": "property", "name": "JLL", "website": "https://www.us.jll.com", "hq": "Los Angeles, CA", "markets": "all", "desc": "Commercial real estate services & property management." },
+    { "cat": "property", "name": "Cushman & Wakefield", "website": "https://www.cushmanwakefield.com", "hq": "Los Angeles, CA", "markets": "all", "desc": "Asset services & commercial property management." },
+    { "cat": "property", "name": "Greystar", "website": "https://www.greystar.com", "hq": "Los Angeles, CA", "markets": "all", "desc": "Largest U.S. multifamily property manager." },
+
+    { "cat": "legal", "name": "Allen Matkins", "website": "https://www.allenmatkins.com", "hq": "Los Angeles, CA", "markets": "all", "desc": "California real estate, land use & construction law firm." },
+    { "cat": "legal", "name": "Cox, Castle & Nicholson", "website": "https://www.coxcastle.com", "hq": "Los Angeles, CA", "markets": "all", "desc": "Real estate, land use and construction law." },
+    { "cat": "legal", "name": "Sheppard Mullin", "website": "https://www.sheppardmullin.com", "hq": "Los Angeles, CA", "markets": "all", "desc": "Full-service firm with a leading real estate practice." },
+
+    { "cat": "construction", "name": "Hathaway Dinwiddie", "website": "https://www.hdcco.com", "hq": "Los Angeles, CA", "markets": "all", "desc": "Major California commercial general contractor." },
+    { "cat": "lenders", "name": "CBRE Capital Markets", "website": "https://www.cbre.com/services/capital-markets", "hq": "Los Angeles, CA", "markets": "all", "desc": "Commercial debt & structured finance for CRE." },
+    { "cat": "escrow", "name": "Commerce Escrow (a Wilshire Quinn company)", "website": "https://www.comescrow.com", "hq": "Los Angeles, CA", "markets": "all", "desc": "Independent commercial escrow & holding services." },
+    { "cat": "developers", "name": "Rising Realty Partners", "website": "https://www.risingrealty.com", "hq": "Los Angeles, CA", "markets": "all", "desc": "Los Angeles-based commercial developer & operator." }
+  ]
+}
diff --git a/public/services.html b/public/services.html
index 63c47f0d..56436d28 100644
--- a/public/services.html
+++ b/public/services.html
@@ -79,6 +79,9 @@
   .badge:hover{filter:brightness(1.08)}
   .st{display:inline-block;font-size:10px;font-weight:800;letter-spacing:.05em;text-transform:uppercase;padding:2px 8px;border-radius:20px;background:var(--wash);color:#4a4f55}
   .st.ok{background:rgba(15,138,77,.12);color:var(--up)}
+  .st.feat{background:#fbf1d8;color:#8a6d1a;border:1px solid #ecdca4}
+  .card.feat{border-color:#ecdca4;background:linear-gradient(180deg,#fffdf7,#fff)}
+  .fhint{color:#8a6d1a;font-size:11px;font-weight:700;margin:6px 2px 0}
   .spec{font-size:12px;color:var(--ink);font-weight:600}
   .loc{color:var(--sub);font-size:12.5px}
   .loc a:hover{color:var(--red);text-decoration:underline}
@@ -206,7 +209,7 @@ function hero(){
   $('kicker').textContent='CRE Services · '+market;
   $('headline').textContent='The firms that make '+m.short+' deals close.';
   $('dek').textContent='A directory of the licensed contractors, lenders, escrow companies, developers and attorneys behind '+m.long+' commercial real estate — drawn from public license registries.';
-  $('note').textContent='Data from public California license registries (CSLB · DFPI · CA DRE · State Bar), for '+m.long+'. RENTV surfaces public registry facts only — verify licensure directly via each record link before engaging a provider.';
+  $('note').textContent='Data from public California license registries (CSLB · DFPI · CA DRE · State Bar), for '+m.long+'. ★ Featured firms are editorially selected major providers shown where a public registry is thin or unavailable (Title, Property Management, Legal). RENTV surfaces public registry facts only — verify licensure and engagement terms directly before engaging a provider.';
   document.title='CRE Services — '+market+' · RENTV.com';
 }
 
@@ -250,7 +253,7 @@ function card(r){
   const spec=r.specialty?`<div class="spec">${esc(r.specialty)}</div>`:'';
   const loc=[r.city&&`<a href="/services?cat=${esc(cat)}&market=${encodeURIComponent(market)}&city=${encodeURIComponent(r.city)}">${esc(cap(r.city))}</a>`,
              r.county&&esc(cap(r.county))+' County', r.zip&&esc(r.zip)].filter(Boolean).join(' · ');
-  const st=r.license_status?`<span class="st${ok?' ok':''}">${esc(cap(r.license_status))}</span>`:'';
+  const st=r.featured?`<span class="st feat">★ Featured</span>`:(r.license_status?`<span class="st${ok?' ok':''}">${esc(cap(r.license_status))}</span>`:'');
   const lic=r.license_no?`<div class="lic">${esc(r.source_label||'License')} #${esc(r.license_no)}</div>`:'';
   const acts=[];
   if(r.phone) acts.push(`<a class="act p" href="tel:${esc(String(r.phone).replace(/[^0-9+]/g,''))}">☎ ${esc(r.phone)}</a>`);
@@ -273,14 +276,18 @@ async function load(reset){
   if(q)u.set('q',q); if(city)u.set('city',city);
   let d; try{ d=await (await fetch('/api/services?'+u.toString())).json(); }catch(e){ if(my===seq)$('meta').textContent='Services directory unavailable — try again.'; return; }
   if(my!==seq)return;
-  total=d.total||0;
+  total=d.total||0;                          // registry rows only
+  const featuredTotal=d.featuredTotal||0;    // curated firms (pinned, page 1 only)
+  const featured=reset?(d.featured||[]):[];
   const rows=d.rows||[];
-  const html=rows.map(card).join('');
-  if(reset)$('rows').innerHTML=html; else $('rows').insertAdjacentHTML('beforeend',html);
+  const grand=total+featuredTotal;
+  if(!grand){ $('meta').textContent=''; $('rows').innerHTML='<div class="empty"><h3>No providers found</h3><div>Try a different name, city or category.</div></div>'; $('more').style.display='none'; return; }
+  const html=featured.map(card).join('')+rows.map(card).join('');
+  if(reset)$('rows').innerHTML=html; else $('rows').insertAdjacentHTML('beforeend',rows.map(card).join(''));
   document.querySelectorAll('.badge[data-cat]').forEach(b=>b.onclick=()=>setCat(b.dataset.cat));
-  if(!total){ $('meta').textContent=''; $('rows').innerHTML='<div class="empty"><h3>No providers found</h3><div>Try a different name, city or category.</div></div>'; $('more').style.display='none'; return; }
   const label=(FACETS.cats.find(c=>c.key===cat)||{}).label||'providers';
-  $('meta').innerHTML=`${total.toLocaleString()} ${esc(label)}${city?` in ${esc(cap(city))}`:''}${q?` matching “${esc(q)}”`:''} · showing ${Math.min(offset+rows.length,total).toLocaleString()}`;
+  const shown=Math.min(featuredTotal+offset+rows.length,grand);
+  $('meta').innerHTML=`${grand.toLocaleString()} ${esc(label)}${city?` in ${esc(cap(city))}`:''}${q?` matching “${esc(q)}”`:''}${featuredTotal?` · ${featuredTotal} featured`:''} · showing ${shown.toLocaleString()}`;
   offset+=rows.length;
   $('more').style.display=offset<total?'block':'none';
 }
diff --git a/scripts/build-services-content.mjs b/scripts/build-services-content.mjs
index d61471d3..f546f0a9 100644
--- a/scripts/build-services-content.mjs
+++ b/scripts/build-services-content.mjs
@@ -31,6 +31,10 @@ const CATS = [
     src: 'active commercial real estate developers' },
   { key: 'legal', label: 'Legal', role: 'Attorney',
     src: 'real estate attorneys' },
+  { key: 'title', label: 'Title', role: null,
+    src: 'title insurance & closing companies' },
+  { key: 'property', label: 'Property Management', role: null,
+    src: 'commercial property & asset management firms' },
 ];
 
 async function ollama(prompt) {
diff --git a/server.js b/server.js
index 68e15dc0..f845482d 100644
--- a/server.js
+++ b/server.js
@@ -269,6 +269,25 @@ app.get('/api/videos', (_q, r) => {
   r.json(base);
 });
 
+// ── Latest CRE Talk episode (public) — powers the front-page featured video so it always
+//    shows the newest episode instead of a hard-coded id. Reads the prod-cron vimeo-library,
+//    filters to "CRE Talk Episode #N", returns the highest N. Lightweight, public fields only. ──
+app.get('/api/cre-talk-latest', (_q, r) => {
+  r.set('Cache-Control', 'public, max-age=600');
+  const lib = readJSON('vimeo-library.json', {});
+  const pool = [...asArr(lib.episodes), ...asArr(lib.items), ...asArr(lib.clips)];
+  let best = null, bestN = -1;
+  const seen = new Set();
+  for (const v of pool) {
+    if (!v || !v.id || seen.has(v.id)) continue; seen.add(v.id);
+    const m = String(v.title || '').match(/CRE\s*Talk\s*Episode\s*#?\s*(\d+)/i);
+    if (!m) continue;
+    const n = parseInt(m[1], 10);
+    if (n > bestN) { bestN = n; best = { id: String(v.id), title: v.title, episode: n, url: v.url || ('https://vimeo.com/' + v.id) }; }
+  }
+  r.json(best || {});
+});
+
 // ── Markets: CRE market fundamentals + snapshot (refreshed by pull-markets cron) ──
 app.get('/api/markets', (_q, r) => {
   r.set('Cache-Control', 'public, max-age=300');
@@ -1571,7 +1590,31 @@ const SERVICE_CATS = {
   escrow:       { role: 'Escrow',     label: 'Escrow' },
   developers:   { role: 'Developer',  label: 'Developers' },
   legal:        { role: 'Attorney',   label: 'Legal' },
+  // Title + Property Management have NO public license registry we can read, so they are
+  // FEATURED-only (role:null → 0 registry rows, filled entirely by the curated seed below).
+  title:        { role: null,         label: 'Title' },
+  property:     { role: null,         label: 'Property Management' },
 };
+// Curated real-firm seed (data/services-featured.json) — guarantees >=1 vendor per category per
+// metro where the registry is thin/absent (Title, Property Mgmt, Legal). Loaded once at startup.
+let SERVICE_FEATURED = [];
+try { SERVICE_FEATURED = (JSON.parse(fs.readFileSync(path.join(DATA, 'services-featured.json'), 'utf8')).vendors) || []; }
+catch (e) { console.warn('[services] no services-featured.json (running without featured seed)'); }
+function featuredFor(catKey, market, q) {
+  const ql = String(q || '').toLowerCase();
+  return SERVICE_FEATURED
+    .filter(v => v.cat === catKey && (v.markets === 'all' || (Array.isArray(v.markets) && v.markets.includes(market))))
+    .filter(v => !ql || String(v.name).toLowerCase().includes(ql))
+    .map(v => ({
+      id: 'f-' + catKey + '-' + String(v.name).replace(/\W+/g, '').toLowerCase(),
+      role: (SERVICE_CATS[catKey] || {}).label || catKey, name: v.name,
+      city: v.hq || null, county: null, zip: null, market,
+      phone: null, website: v.website || null,
+      license_no: null, license_type: null, license_status: 'Featured',
+      specialty: v.desc || null, source: 'featured', source_label: 'Featured',
+      source_url: null, featured: true,
+    }));
+}
 const SERVICE_MARKETS = new Set(['Greater LA', 'Orange County', 'San Diego', 'Inland Empire', 'Ventura', 'Arizona', 'SoCal (other)']);
 // Copy generated by scripts/build-services-content.mjs (LOCAL Ollama, $0). Loaded once at startup.
 let SERVICE_CONTENT = { intro: {}, categories: {} };
@@ -1639,19 +1682,31 @@ app.get('/api/services', async (req, res) => {
       'SELECT id, role, entity_name, license_no, license_type, license_status, city, county, zip, market, phone, website, source, source_url ' +
       'FROM rentv_licensed_targets WHERE ' + whereSql + ' ORDER BY ' + orderSql +
       ' LIMIT ' + limit + ' OFFSET ' + offset, params);
+    // Curated featured firms are PINNED to page 1 (offset 0) and only when no city filter is
+    // applied (they serve the whole metro, not one city). They guarantee >=1 vendor per category.
+    const featured = (offset === 0 && !city) ? featuredFor(catKey, market, q) : [];
     res.set('Cache-Control', 'public, max-age=120');
-    res.json({ cat: catKey, label: cat.label, role: cat.role, market, sort, total: totalR.rows[0].n, offset, rows: rowsR.rows.map(serviceRow) });
-  } catch (e) { res.status(502).json({ rows: [], total: 0, error: 'services registry unavailable' }); }
+    res.json({
+      cat: catKey, label: cat.label, role: cat.role, market, sort,
+      total: totalR.rows[0].n, featuredTotal: featured.length, offset,
+      featured, rows: rowsR.rows.map(serviceRow),
+    });
+  } catch (e) { res.status(502).json({ rows: [], featured: [], total: 0, error: 'services registry unavailable' }); }
 });
 app.get('/api/services/facets', async (req, res) => {
   try {
     const market = SERVICE_MARKETS.has(String(req.query.market)) ? String(req.query.market) : 'Greater LA';
     const r = await rePool.query('SELECT role, count(*)::int n FROM rentv_licensed_targets WHERE within_300mi AND market = $1 GROUP BY role', [market]);
     const byRole = Object.fromEntries(r.rows.map(x => [x.role, x.n]));
-    const cats = Object.entries(SERVICE_CATS).map(([key, c]) => ({
-      key, label: c.label, role: c.role, count: byRole[c.role] || 0,
-      blurb: (SERVICE_CONTENT.categories[key] || {}).blurb || '',
-    }));
+    const cats = Object.entries(SERVICE_CATS).map(([key, c]) => {
+      const featuredN = featuredFor(key, market, '').length;
+      return {
+        key, label: c.label, role: c.role,
+        count: (byRole[c.role] || 0) + featuredN,   // registry + curated featured
+        registryCount: byRole[c.role] || 0, featuredCount: featuredN,
+        blurb: (SERVICE_CONTENT.categories[key] || {}).blurb || '',
+      };
+    });
     // Top cities across the market (for the city drill-down / filter chips) — public registry data.
     const cityR = await rePool.query(
       "SELECT city, count(*)::int n FROM rentv_licensed_targets WHERE within_300mi AND market=$1 AND city IS NOT NULL AND city <> '' GROUP BY city ORDER BY n DESC LIMIT 24", [market]);

← 71ec8d49 fix(auth): bridge server-admin session into /api/pr so deals  ·  back to Rentv  ·  PR-intel: add found_role_corroborated status (DTD verdict C) 78a39e80 →