← back to Homesonspec
collectors: add Mattamy Homes — cracked the 'bucket-D' national via Sitecore JSS feed
5c09c6903fb35a437603ce3ff036cad595cbb262 · 2026-07-29 09:13:58 -0700 · Steve Abrams
Prior recon marked Mattamy bucket-D-hard (map feed not isolated). Wrong: its Sitecore JSS layout API
(GET /sitecore/api/layout/render/jss?item=/search-data&sc_apikey={anon-public-key}&market=<State>&IsState=1)
returns a whole state's QMI inventory per call — anonymous key (not a credential), honest-UA, no anti-bot,
robots-allowed. Emits qmiCards (per-home), ignores planCards/communityCards (aggregates). 4 US states
(AZ/FL/NC/TX). DB-verified: 767 homes, 100% price/beds/baths/sqft/geo, 0 bad-bbox pins, 767 distinct
addresses. New builder -> created Builder + SourceRegistry (FK). Every-sweep in the loop. Built via
isolated subagent + serial gated integration. (Richmond American: reachable but Blazor-SSR -> needs a
shared browser RenderFetcher, deferred w/ RECON.md.)
Files touched
M apps/workers/package.jsonM apps/workers/src/cli.tsM pnpm-lock.yamlM scripts/build-loop.sh
Diff
commit 5c09c6903fb35a437603ce3ff036cad595cbb262
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Wed Jul 29 09:13:58 2026 -0700
collectors: add Mattamy Homes — cracked the 'bucket-D' national via Sitecore JSS feed
Prior recon marked Mattamy bucket-D-hard (map feed not isolated). Wrong: its Sitecore JSS layout API
(GET /sitecore/api/layout/render/jss?item=/search-data&sc_apikey={anon-public-key}&market=<State>&IsState=1)
returns a whole state's QMI inventory per call — anonymous key (not a credential), honest-UA, no anti-bot,
robots-allowed. Emits qmiCards (per-home), ignores planCards/communityCards (aggregates). 4 US states
(AZ/FL/NC/TX). DB-verified: 767 homes, 100% price/beds/baths/sqft/geo, 0 bad-bbox pins, 767 distinct
addresses. New builder -> created Builder + SourceRegistry (FK). Every-sweep in the loop. Built via
isolated subagent + serial gated integration. (Richmond American: reachable but Blazor-SSR -> needs a
shared browser RenderFetcher, deferred w/ RECON.md.)
---
apps/workers/package.json | 3 ++-
apps/workers/src/cli.ts | 2 ++
pnpm-lock.yaml | 25 +++++++++++++++++++++++++
scripts/build-loop.sh | 5 ++++-
4 files changed, 33 insertions(+), 2 deletions(-)
diff --git a/apps/workers/package.json b/apps/workers/package.json
index 4a1300fc..906c8375 100644
--- a/apps/workers/package.json
+++ b/apps/workers/package.json
@@ -45,7 +45,8 @@
"@homesonspec/collector-holt-homes": "workspace:*",
"@homesonspec/collector-fischer-homes": "workspace:*",
"@homesonspec/collector-fulton-homes": "workspace:*",
- "@homesonspec/collector-gl-homes": "workspace:*"
+ "@homesonspec/collector-gl-homes": "workspace:*",
+ "@homesonspec/collector-mattamy": "workspace:*"
},
"devDependencies": {
"tsx": "^4.19.2",
diff --git a/apps/workers/src/cli.ts b/apps/workers/src/cli.ts
index 582ac70b..1d06a2d6 100644
--- a/apps/workers/src/cli.ts
+++ b/apps/workers/src/cli.ts
@@ -26,6 +26,7 @@ import { holtHomesAdapter } from "@homesonspec/collector-holt-homes";
import { fischerHomesAdapter } from "@homesonspec/collector-fischer-homes";
import { fultonHomesAdapter } from "@homesonspec/collector-fulton-homes";
import { glHomesAdapter } from "@homesonspec/collector-gl-homes";
+import { mattamyAdapter } from "@homesonspec/collector-mattamy";
import { runPipeline } from "./pipeline";
import { recordSourceRun } from "./verify";
@@ -61,6 +62,7 @@ const ADAPTERS = {
[fischerHomesAdapter.key]: fischerHomesAdapter,
[fultonHomesAdapter.key]: fultonHomesAdapter,
[glHomesAdapter.key]: glHomesAdapter,
+ [mattamyAdapter.key]: mattamyAdapter,
};
async function main() {
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index f7808598..b001946e 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -196,6 +196,9 @@ importers:
'@homesonspec/collector-lgi-homes':
specifier: workspace:*
version: link:../../collectors/lgi-homes
+ '@homesonspec/collector-mattamy':
+ specifier: workspace:*
+ version: link:../../collectors/mattamy
'@homesonspec/collector-meridian-homes':
specifier: workspace:*
version: link:../../collectors/meridian-homes
@@ -676,6 +679,28 @@ importers:
specifier: ^4.0.0
version: 4.1.10(@types/node@22.20.1)(vite@8.1.5(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1))
+ collectors/mattamy:
+ dependencies:
+ '@homesonspec/collectors-common':
+ specifier: workspace:*
+ version: link:../common
+ '@homesonspec/schemas':
+ specifier: workspace:*
+ version: link:../../packages/schemas
+ '@homesonspec/shared':
+ specifier: workspace:*
+ version: link:../../packages/shared
+ devDependencies:
+ '@types/node':
+ specifier: ^22.10.5
+ version: 22.20.1
+ typescript:
+ specifier: ^5.7.2
+ version: 5.9.3
+ vitest:
+ specifier: ^4.0.0
+ version: 4.1.10(@types/node@22.20.1)(vite@8.1.5(@types/node@22.20.1)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.23.1))
+
collectors/meridian-homes:
dependencies:
'@homesonspec/collectors-common':
diff --git a/scripts/build-loop.sh b/scripts/build-loop.sh
index 36c0a7b8..a3a44ba3 100644
--- a/scripts/build-loop.sh
+++ b/scripts/build-loop.sh
@@ -133,6 +133,8 @@ sweep_fischer() { FISCHER_PAGE_LIMIT=20 CLI fischer-homes-site | sed "s/^/
# Extracts own-home price/beds/sqft + geo from each page's ld+json (fixed 2026-07-29). Honest-null
# where a page lacks its own home in ld+json.
sweep_dreamfinders() { DREAMFINDERS_PAGE_LIMIT=600 CLI dream-finders-site | sed "s/^/ df NATIONAL: /"; }
+# Mattamy = Sitecore JSS layout API, 4 fast state GETs (AZ/FL/NC/TX, ~767 homes) — every sweep.
+sweep_mattamy() { MATTAMY_PAGE_LIMIT=10 CLI mattamy-site | sed "s/^/ mat NATIONAL: /"; }
# metro-iterating adapters (footprint = METROS, not states) — scoped to served metros only
# (Cody WAF-lesson from the start). Ashton Woods publishes per-metro quick-move-in homes.
@@ -152,7 +154,7 @@ while pgrep -f "cli.ts --adapter" 2>/dev/null | grep -qv "^$$\$"; do sleep 20; d
# a transient failure shouldn't permanently sideline a chosen builder, and genuine breakage is
# surfaced by the dashboard's per-source failed_runs + the freshness canary (not silent). To
# retire a builder, remove it from THIS list (don't rely on auto-pause surviving a restart).
-for k in dr-horton-site kb-home-site pultegroup-site tri-pointe-site lennar-site toll-brothers-site david-weekley-site taylor-morrison-site ashton-woods-site discovery-homes-site meritage-homes-site ryan-homes-site highland-homes-site landsea-homes-site shea-homes-site lgi-homes-site century-communities-site beazer-site drees-homes-site perry-homes-site brookfield-site holt-homes-site fulton-homes-site gl-homes-site fischer-homes-site dream-finders-site; do
+for k in dr-horton-site kb-home-site pultegroup-site tri-pointe-site lennar-site toll-brothers-site david-weekley-site taylor-morrison-site ashton-woods-site discovery-homes-site meritage-homes-site ryan-homes-site highland-homes-site landsea-homes-site shea-homes-site lgi-homes-site century-communities-site beazer-site drees-homes-site perry-homes-site brookfield-site holt-homes-site fulton-homes-site gl-homes-site fischer-homes-site dream-finders-site mattamy-site; do
PSQL "update \"SourceRegistry\" set active=true, health='HEALTHY', \"consecutiveFailures\"=0 where key='$k';" >/dev/null
done
@@ -172,6 +174,7 @@ while [ ! -f "$STOP" ] && [ "$sweep" -lt "$MAX_SWEEPS" ]; do
sweep_shea &
sweep_perry &
sweep_brookfield &
+ sweep_mattamy &
sweep_fulton &
sweep_gl &
# heavy crawlers: throttled to every 4th sweep (hundreds of GETs each, slow-changing data)
← 718fc16b auto-save: 2026-07-29T09:07:36 (1 files) — collectors/mattam
·
back to Homesonspec
·
auto-save: 2026-07-29T09:37:47 (1 files) — collectors/richmo 63d56d74 →