← Back to gallery

U3 — Customer Display rework PROD

2026-05-25 Gate 2 ship — 4th slice of the day. Three Customer Display changes from Narong's Test-Run #3 doc red highlights. Migration applied to prod Supabase; full settings save → reload round-trip verified on lumiere-coffee.

Summary

Status
11/11 prod · 15/15 local · typecheck clean
Commits
nix-outdoor-sales-backend c7fb9a7 · nix-cafe c51aae4
Files
6 modified + 1 new migration · ~130 LOC net new
Tested on
lumiere-coffee.nixtech.app (Starter)

U3.1 — Idle screen full-bleed when promo is set

Before: idle stacked logo / storeName / Welcome / promoText / promo-image vertically — busy and the promo was small.

After: when promoImageUrl OR slideshowEnabled + slideshowImages is set, render edge-to-edge promo (no chrome). Falls back to the legacy branded layout when no promo content is set. New fullBleed prop on the Slideshow component (defaults false for back-compat).

U3.2 — Cart screen 50/50 split during checkout

Before: while the cashier rings up items, the customer display rendered a full-width cart.

After: when a portrait promo image is configured, the cart screen splits 50/50 — cart column on the left (header + lines + total footer), portrait promo on the right (object-contain on black). No portrait set → falls back to full-width cart. data-split="true"/"false" testid attribute exposes the active mode.

U3.3 — Portrait PROMO image upload

Settings UI: new "Portrait promo image URL" field in Settings > Customer Display, directly under the existing landscape "Promo image URL" field. Same UploadButton component. Hint copy: "Portrait image shown on the right half of the customer display DURING CHECKOUT (cart visible on the left). Use a vertical image (e.g. 1080×1920). Leave blank to skip."

Schema: 1 new col cafe.tenant_config.display_promo_portrait_url VARCHAR(1024), nullable. Migration applied to prod Supabase post-push.

Future expansion: stored as a single VARCHAR for now. If Narong later wants portrait slideshow rotation (like the existing landscape one), it's a small 2-col follow-up migration — same shape as the existing landscape slideshow path.

11/11 prod checks

Prod: cafe.tenant_config has display_promo_portrait_url
Snapshot current display_promo_portrait_url for restore
DAO probe: getDisplayBranding + saveDisplayBranding round-trip promoPortraitUrl on prod
Login to lumiere-coffee
/cafe/settings/display renders new Portrait promo field
Settings: fill + save the portrait URL
Reload settings → portrait URL persisted via prod Supabase round-trip
Settings: clear the portrait URL + save
Reload → portrait URL cleared (null on DB)
Restore original portrait URL
No 5xx HTTP responses during the suite

Lumiere's original portrait URL value snapshotted at start, restored at the end via SQL (idempotent — also restored on process.exit).

Screenshots

Regression sweep

51/51 regression green · 11/11 U3 prod = 62/62 total. No regressions from this push.
test-phase1-prod.mjs11/11 (narongix)
test-phase2-sso-outdoor-prod.mjs6/6 (narongix)
test-phase2-cafe-multishop-prod.mjs6/6 (demo) · solo run per feedback_phase2_cafe_multishop_solo_retry — first-attempt green (4th time today)
test-m1-prod.mjs10/10 (narongix)
test-r7-prod.mjs14/14 (narongix + lumiere)
test-r8-prod.mjs4/4 (narongix)
test-u3-prod.mjs11/11 (lumiere — this slice)

Notes for Narong

Day's progress (2026-05-25)