← back to Homesonspec
kb-home: capture listing photos (ThumbnailImage/GalleryPhotos are objects, not strings)
cb83a522dd7d8a173ca4bbeeb8bffd8829290cd5 · 2026-07-28 20:17:45 -0700 · Steve Abrams
KB's feed stores images as objects {Image,Caption,…} (ThumbnailImage) and an
array of them (GalleryPhotos); the URL lives under .Image (a relative /globalassets
path). The adapter read them via str()/split() -> both null -> 0 photos on all 526
homes. Fixed to read .Image, build thumb+gallery, absolutize, drop coming-soon
placeholders. National FORCE_REEXTRACT backfill: 0 -> 521/526 (99.0%), 212 w/ galleries.
Verified: URL loads 200; KB detail + search cards render, 0 broken.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
M collectors/kb-home/src/index.ts
Diff
commit cb83a522dd7d8a173ca4bbeeb8bffd8829290cd5
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Tue Jul 28 20:17:45 2026 -0700
kb-home: capture listing photos (ThumbnailImage/GalleryPhotos are objects, not strings)
KB's feed stores images as objects {Image,Caption,…} (ThumbnailImage) and an
array of them (GalleryPhotos); the URL lives under .Image (a relative /globalassets
path). The adapter read them via str()/split() -> both null -> 0 photos on all 526
homes. Fixed to read .Image, build thumb+gallery, absolutize, drop coming-soon
placeholders. National FORCE_REEXTRACT backfill: 0 -> 521/526 (99.0%), 212 w/ galleries.
Verified: URL loads 200; KB detail + search cards render, 0 broken.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
collectors/kb-home/src/index.ts | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/collectors/kb-home/src/index.ts b/collectors/kb-home/src/index.ts
index 2fb0529a..ca7066a5 100644
--- a/collectors/kb-home/src/index.ts
+++ b/collectors/kb-home/src/index.ts
@@ -123,8 +123,18 @@ export const kbHomeAdapter: SourceAdapter = {
const address = str(r.Address);
const communityName = str(r.CommunityName);
if (!address || !communityName) continue;
- const thumb = str(r.ThumbnailImage) ?? str(r.GalleryPhotos)?.split(",")[0]?.trim() ?? null;
- const image = thumb ? (thumb.startsWith("http") ? thumb : ORIGIN + thumb) : null;
+ // KB's ThumbnailImage is an OBJECT {Image,Caption,…} and GalleryPhotos an ARRAY
+ // of such objects — the URL lives under `.Image` (a site-relative /globalassets
+ // path), NOT the object itself. The old str()/split() read both as null, so KB
+ // had 0 photos. Build thumb-first + gallery, absolutize, drop "coming soon"
+ // placeholders (worse than the clean gradient fallback). [recon 2026-07-28]
+ const imgUrl = (o: unknown): string | null => str((o as Record<string, unknown> | undefined)?.Image);
+ const gallery = Array.isArray(r.GalleryPhotos) ? (r.GalleryPhotos as unknown[]) : [];
+ const rawImgs = [imgUrl(r.ThumbnailImage), ...gallery.map(imgUrl)].filter((u): u is string => !!u);
+ const images = [...new Set(rawImgs)]
+ .filter((u) => !/photo-coming-soon|\/images\/default\//i.test(u))
+ .map((u) => (u.startsWith("http") ? u : ORIGIN + u))
+ .slice(0, 8);
const lot = str(r.Homesite) ?? str(r.MLSNumber);
const homeType = /town|condo|attached/i.test(str(r.HomeType) ?? "") ? "TOWNHOME" : "SINGLE_FAMILY";
records.push({
@@ -154,7 +164,7 @@ export const kbHomeAdapter: SourceAdapter = {
builderInventoryId: fv(lot, lot, page.url),
planName: fv(str(r.FloorPlanName), str(r.FloorPlanName), page.url),
availabilityStatus: fv(str(r.MoveInDateCopy), str(r.MoveInDateCopy), page.url),
- images: fv<string[]>(image ? [image] : [], null, page.url, image ? "builder listing photo" : null),
+ images: fv<string[]>(images, null, page.url, images.length ? "builder listing photo" : null),
},
});
}
← d9241682 collectors: add LGI, Shea, Century, Beazer, Drees adapters (
·
back to Homesonspec
·
david-weekley: capture per-home ElevationRendering photos fr 7f27ee91 →