[object Object]

← back to Costa Rica

app API: expose region_image_url so listings can fall back (additive)

26bd9e3e31ae25ca67378c204d1842a5c4bd7134 · 2026-09-12 08:48:07 -0700 · Steve

Every bookable listing renders imageless: places.image_url is null on all of
them, nothing has ever populated that column (every image ingest targets
regions), and the listings query had no fallback - it joined regions but took
only name and slug.

Measured: 8 of 9 bookable listings sit in a region that HAS a real Wikimedia
image (regions_with_image = 49 of 102); only Eden Atenas's region has none. So a
fallback is viable today, which is the cheap alternative to building the
per-listing image-sourcing pipeline that does not exist and that nobody asked
for.

Purely additive: image_url is unchanged, the new field is separately named, no
existing consumer breaks, and where a region has no image it is simply null -
strictly non-worsening. The client-side fallback is a separate change and is NOT
made here.

Refs TK-11518.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Files touched

Diff

commit 26bd9e3e31ae25ca67378c204d1842a5c4bd7134
Author: Steve <steve@designerwallcoverings.com>
Date:   Sat Sep 12 08:48:07 2026 -0700

    app API: expose region_image_url so listings can fall back (additive)
    
    Every bookable listing renders imageless: places.image_url is null on all of
    them, nothing has ever populated that column (every image ingest targets
    regions), and the listings query had no fallback - it joined regions but took
    only name and slug.
    
    Measured: 8 of 9 bookable listings sit in a region that HAS a real Wikimedia
    image (regions_with_image = 49 of 102); only Eden Atenas's region has none. So a
    fallback is viable today, which is the cheap alternative to building the
    per-listing image-sourcing pipeline that does not exist and that nobody asked
    for.
    
    Purely additive: image_url is unchanged, the new field is separately named, no
    existing consumer breaks, and where a region has no image it is simply null -
    strictly non-worsening. The client-side fallback is a separate change and is NOT
    made here.
    
    Refs TK-11518.
    
    Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
---
 routes/app.js | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/routes/app.js b/routes/app.js
index 73030a1..72b43de 100644
--- a/routes/app.js
+++ b/routes/app.js
@@ -117,6 +117,12 @@ router.get('/listings', optionalAuth, async (req, res) => {
   const page = 'LIMIT ' + lim + ' OFFSET ' + off; // clamped integers, no injection surface
   const { rows } = await pool.query(
     `SELECT p.slug, p.name, p.vertical, p.category, p.description, p.image_url, p.rating,
+            -- Nothing has ever populated places.image_url (every image ingest targets REGIONS),
+            -- so every listing renders imageless with no fallback. Expose the region image as a
+            -- clearly-named SEPARATE field so the client can fall back to it. Purely ADDITIVE:
+            -- image_url is unchanged, so no existing consumer breaks, and if a region has no
+            -- image this is simply null — strictly non-worsening. (TK-11518)
+            r.image_url AS region_image_url,
             r.name AS region, r.slug AS region_slug, p.lat, p.lng,
             pb.booking_type, pb.currency, pb.base_price, pb.cleaning_fee, pb.max_guests, pb.instant_book
        FROM place_booking pb

← 5cf7dca costa-rica: fix date-dependent payouts test (113/113 green)  ·  back to Costa Rica  ·  costa-rica: bound live provider fetch with a timeout (PRE-FL a3d5084 →