[object Object]

← back to Commercialrealestate

CRE: expand geographic scope to all of LA County (88 cities + neighborhoods + unincorporated)

2674ef82b8240bc8fbecd12e4c6e8fce41be082b · 2026-06-26 23:40:23 -0700 · Steve

Files touched

Diff

commit 2674ef82b8240bc8fbecd12e4c6e8fce41be082b
Author: Steve <steve@designerwallcoverings.com>
Date:   Fri Jun 26 23:40:23 2026 -0700

    CRE: expand geographic scope to all of LA County (88 cities + neighborhoods + unincorporated)
---
 data/listings.json           |  2 +-
 data/ranked.json             |  2 +-
 scripts/refresh-all.js       |  9 ++---
 scripts/sources/firms.js     | 29 +++++++--------
 scripts/sources/la-county.js | 88 ++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 108 insertions(+), 22 deletions(-)

diff --git a/data/listings.json b/data/listings.json
index 1307e25..0bd7a50 100644
--- a/data/listings.json
+++ b/data/listings.json
@@ -1,6 +1,6 @@
 {
   "meta": {
-    "market": "San Fernando Valley, CA",
+    "market": "Los Angeles County, CA",
     "asset_classes": [
       "Multifamily",
       "Retail/Net-lease",
diff --git a/data/ranked.json b/data/ranked.json
index e2efb97..33839e0 100644
--- a/data/ranked.json
+++ b/data/ranked.json
@@ -1,6 +1,6 @@
 {
   "meta": {
-    "market": "San Fernando Valley, CA",
+    "market": "Los Angeles County, CA",
     "asset_classes": [
       "Multifamily",
       "Retail/Net-lease",
diff --git a/scripts/refresh-all.js b/scripts/refresh-all.js
index 025612d..7a1c075 100644
--- a/scripts/refresh-all.js
+++ b/scripts/refresh-all.js
@@ -17,18 +17,17 @@ const path = require('path');
 const { chromium } = require('playwright-core');
 const Browserbase = require('@browserbasehq/sdk').default;
 const { TYPES, norm, today, FIRMS, byKey, toListing, inBand } = require('./sources/firms');
+const { NAV_HUBS } = require('./sources/la-county');
 
 const ROOT = path.join(__dirname, '..');
 const bbEnv = fs.readFileSync(process.env.HOME + '/.claude/skills/browserbase/.env', 'utf8');
 const get = (t, k) => (t.match(new RegExp('^' + k + '=(.*)$', 'm')) || [])[1]?.replace(/['"]/g, '').trim();
 
+// Geo scope is all of LA County (filter side). For navigation we visit the submarket HUBS by
+// default (sweeping all 88 cities in one session is infeasible); override with CC_NAV.
 const NAV_CITIES = process.env.CC_NAV
   ? process.env.CC_NAV.split(',').map(s => s.trim())
-  : ['Van Nuys', 'Reseda', 'North Hollywood', 'Northridge', 'Panorama City', 'Canoga Park',
-     'Sherman Oaks', 'Sun Valley', 'Encino', 'Granada Hills', 'Woodland Hills', 'Tarzana',
-     'Studio City', 'Chatsworth',
-     // Eastside / Westside expansion (2026-06-27):
-     'Silver Lake', 'West Hollywood', 'Santa Monica'];
+  : NAV_HUBS;
 
 // Which firms to run. Default = verified only, so an unattended cron never silently scrapes an
 // unconfirmed firm. Pass CC_FIRMS to opt specific firms in.
diff --git a/scripts/sources/firms.js b/scripts/sources/firms.js
index 600f373..40279b8 100644
--- a/scripts/sources/firms.js
+++ b/scripts/sources/firms.js
@@ -16,21 +16,20 @@
 
 'use strict';
 
-// ── Shared market filter (single source of truth; was duplicated inline in refresh-listings.js) ──
-// Named SFV for history, but now the full target-market set: San Fernando Valley + select
-// Eastside/Westside submarkets (Silver Lake, West Hollywood, Santa Monica). NOTE: the premium
-// Westside cities (Santa Monica, West Hollywood) typically clear the $1.75M band, so widen MAXP if
-// you want real coverage there. Silver Lake assets sometimes surface under city "Los Angeles" in
-// feeds — kept out deliberately to avoid pulling all of LA; revisit if Silver Lake yield is 0.
-const SFV = new Set(['van nuys', 'reseda', 'north hollywood', 'northridge', 'panorama city',
-  'canoga park', 'sherman oaks', 'sun valley', 'encino', 'granada hills', 'tarzana', 'woodland hills',
-  'winnetka', 'west hills', 'lake balboa', 'valley village', 'valley glen', 'studio city', 'toluca lake',
-  'arleta', 'pacoima', 'mission hills', 'sylmar', 'tujunga', 'sunland', 'porter ranch', 'chatsworth',
-  'north hills',
-  // Eastside / Westside expansion (2026-06-27):
-  'silver lake', 'silverlake', 'west hollywood', 'santa monica']);
-
-const MINP = 800000, MAXP = 1750000;
+const { LA_COUNTY, inLACounty } = require('./la-county');
+
+// ── Shared market filter ─────────────────────────────────────────────────────────────────────────
+// Scope is now ALL of Los Angeles County (per Steve, 2026-06-27 "all LA county frankly"). The geo
+// gate is the canonical LA_COUNTY place set in la-county.js (88 incorporated cities + major LA
+// neighborhoods + unincorporated communities). `SFV` is kept as an alias so any older import that
+// references it still works — it now points at the full county set.
+const SFV = LA_COUNTY;
+
+// Price band reflects the $400k-down, leveraged budget frame. NOTE: county-wide scope now includes
+// premium markets (Beverly Hills, Malibu, Pacific Palisades, Santa Monica) whose entry prices clear
+// $1.75M — those will return little until MAXP is widened. Override via env for a wider sweep.
+const MINP = +(process.env.CC_MINP || 800000);
+const MAXP = +(process.env.CC_MAXP || 1750000);
 
 // Address-normalizer used as the cross-firm dedup key (identical rules to the original refresh).
 const norm = s => String(s || '').toLowerCase()
diff --git a/scripts/sources/la-county.js b/scripts/sources/la-county.js
new file mode 100644
index 0000000..d8af980
--- /dev/null
+++ b/scripts/sources/la-county.js
@@ -0,0 +1,88 @@
+// sources/la-county.js — canonical Los Angeles County place set, used as the geographic in-band gate.
+//
+// WHY: the tracker started SFV-only with a hand-kept neighborhood allowlist. Scope is now "all LA
+// County" — so instead of appending cities one batch at a time, this is the authoritative set every
+// captured listing's city is checked against. Covers (1) all 88 incorporated cities, (2) the major
+// City-of-Los-Angeles neighborhoods that appear as "city" in listing feeds, and (3) the common
+// unincorporated communities (Altadena, Marina del Rey, Topanga, East LA, etc.). Names are stored
+// lowercased; match with LA_COUNTY.has(city.trim().toLowerCase()).
+//
+// Maintenance: if a real in-county listing is dropped because its feed used a name not here, add the
+// alias — don't loosen to a substring match (that would pull Orange/Ventura/SB county bleed).
+
+'use strict';
+
+// (1) The 88 incorporated cities of Los Angeles County.
+const INCORPORATED = [
+  'agoura hills', 'alhambra', 'arcadia', 'artesia', 'avalon', 'azusa', 'baldwin park', 'bell',
+  'bell gardens', 'bellflower', 'beverly hills', 'bradbury', 'burbank', 'calabasas', 'carson',
+  'cerritos', 'claremont', 'commerce', 'compton', 'covina', 'cudahy', 'culver city', 'diamond bar',
+  'downey', 'duarte', 'el monte', 'el segundo', 'gardena', 'glendale', 'glendora', 'hawaiian gardens',
+  'hawthorne', 'hermosa beach', 'hidden hills', 'huntington park', 'industry', 'city of industry',
+  'inglewood', 'irwindale', 'la canada flintridge', 'la cañada flintridge', 'la habra heights',
+  'la mirada', 'la puente', 'la verne', 'lakewood', 'lancaster', 'lawndale', 'lomita', 'long beach',
+  'los angeles', 'lynwood', 'malibu', 'manhattan beach', 'maywood', 'monrovia', 'montebello',
+  'monterey park', 'norwalk', 'palmdale', 'palos verdes estates', 'paramount', 'pasadena',
+  'pico rivera', 'pomona', 'rancho palos verdes', 'redondo beach', 'rolling hills',
+  'rolling hills estates', 'rosemead', 'san dimas', 'san fernando', 'san gabriel', 'san marino',
+  'santa clarita', 'santa fe springs', 'santa monica', 'sierra madre', 'signal hill', 'south el monte',
+  'south gate', 'south pasadena', 'temple city', 'torrance', 'vernon', 'walnut', 'west covina',
+  'west hollywood', 'westlake village', 'whittier'
+];
+
+// (2) Major City-of-Los-Angeles neighborhoods that show up as the "city" field in listing feeds.
+const LA_NEIGHBORHOODS = [
+  // San Fernando Valley
+  'van nuys', 'reseda', 'north hollywood', 'northridge', 'panorama city', 'canoga park', 'sherman oaks',
+  'sun valley', 'encino', 'granada hills', 'tarzana', 'woodland hills', 'winnetka', 'west hills',
+  'lake balboa', 'valley village', 'valley glen', 'studio city', 'toluca lake', 'arleta', 'pacoima',
+  'mission hills', 'sylmar', 'tujunga', 'sunland', 'porter ranch', 'chatsworth', 'north hills',
+  'sepulveda', 'shadow hills', 'lake view terrace', 'cahuenga pass',
+  // Westside
+  'pacific palisades', 'brentwood', 'westwood', 'west los angeles', 'sawtelle', 'mar vista', 'venice',
+  'playa del rey', 'playa vista', 'palms', 'cheviot hills', 'rancho park', 'century city',
+  'beverly crest', 'bel air', 'bel-air',
+  // Central / Eastside
+  'hollywood', 'east hollywood', 'west hollywood', 'hancock park', 'larchmont', 'koreatown',
+  'mid-city', 'mid city', 'mid-wilshire', 'pico-union', 'pico union', 'westlake', 'silver lake',
+  'silverlake', 'echo park', 'los feliz', 'atwater village', 'eagle rock', 'highland park',
+  'mount washington', 'glassell park', 'cypress park', 'lincoln heights', 'el sereno', 'boyle heights',
+  'downtown los angeles', 'downtown', 'arts district', 'chinatown', 'historic filipinotown',
+  // South / Harbor
+  'south los angeles', 'south la', 'jefferson park', 'west adams', 'leimert park', 'baldwin hills',
+  'crenshaw', 'view park', 'windsor hills', 'watts', 'san pedro', 'wilmington', 'harbor city',
+  'harbor gateway', 'south park', 'university park', 'exposition park'
+];
+
+// (3) Common unincorporated LA County communities that appear in feeds.
+const UNINCORPORATED = [
+  'altadena', 'marina del rey', 'topanga', 'universal city', 'east los angeles', 'east la',
+  'ladera heights', 'lennox', 'del aire', 'westmont', 'florence-graham', 'florence graham',
+  'willowbrook', 'walnut park', 'west whittier', 'south whittier', 'hacienda heights', 'rowland heights',
+  'avocado heights', 'valinda', 'charter oak', 'citrus', 'vincent', 'covina islands',
+  'south san gabriel', 'east pasadena', 'east san gabriel', 'kinneloa mesa', 'mayflower village',
+  'north el monte', 'south monrovia island', 'valencia', 'newhall', 'saugus', 'canyon country',
+  'stevenson ranch', 'castaic', 'val verde', 'agua dulce', 'acton', 'littlerock', 'quartz hill',
+  'lake los angeles', 'sun village', 'desert view highlands', 'la crescenta', 'la crescenta-montrose',
+  'montrose', 'altadena', 'west carson', 'west compton', 'rancho dominguez', 'east rancho dominguez',
+  'athens', 'west athens', 'ladera', 'view park-windsor hills'
+];
+
+const LA_COUNTY = new Set([...INCORPORATED, ...LA_NEIGHBORHOODS, ...UNINCORPORATED]);
+
+// A practical default set of investment-submarket HUBS to actually navigate (the full 88+ cities is
+// too many to sweep in one Browserbase session). Override at runtime with CC_NAV. The FILTER above
+// stays county-wide regardless, so a hub search that happens to surface a neighboring in-county city
+// is still kept.
+const NAV_HUBS = [
+  'Van Nuys', 'Reseda', 'North Hollywood', 'Sherman Oaks', 'Encino', 'Woodland Hills', 'Northridge',
+  'Canoga Park', 'Studio City', 'Burbank', 'Glendale', 'Pasadena', 'Altadena', 'Los Angeles',
+  'Silver Lake', 'Echo Park', 'Highland Park', 'Hollywood', 'West Hollywood', 'Koreatown',
+  'Culver City', 'Santa Monica', 'Venice', 'Mar Vista', 'Beverly Hills', 'Brentwood',
+  'Pacific Palisades', 'Malibu', 'Inglewood', 'Hawthorne', 'Gardena', 'Torrance', 'Long Beach',
+  'San Pedro', 'Downey', 'Whittier', 'El Monte', 'Pomona', 'Lancaster', 'Palmdale', 'Santa Clarita'
+];
+
+const inLACounty = (city) => LA_COUNTY.has(String(city || '').trim().toLowerCase());
+
+module.exports = { LA_COUNTY, NAV_HUBS, inLACounty, INCORPORATED, LA_NEIGHBORHOODS, UNINCORPORATED };

← 9c2ab88 auto-save: 2026-06-26T23:36:14 (2 files) — scripts/refresh-a  ·  back to Commercialrealestate  ·  CRE: wire read-only WhoLivedThere/pastdoor archive (assessor 690567b →