diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte index 32fba52..1968f15 100644 --- a/frontend/src/routes/+page.svelte +++ b/frontend/src/routes/+page.svelte @@ -12,6 +12,7 @@ let news = $state(null); // {id, title, summary, image, topic, ...} let art = $state(null); // {title, artist, year, image} let newsFit = $state('cover'); // 'cover' = full-bleed photo; 'contain' = framed-plate figure + let newsImgOk = $state(false); // reveal the photo only once it's truly loaded (else the typo cover stays) // Pictureless articles (~half the feed) get a typographic category cover instead of a blank // well: the topic word on a soft topic-tinted field, color-coded across the feed. @@ -112,14 +113,25 @@ try { const it = (await getJSON(`/api/brief?limit=1${homeq}${q ? '&' + q : ''}`))?.items?.[0]; if (it) news = { id: it.id, title: it.title, summary: it.summary || it.description || '', image: it.image_url || null, topic: it.topic || null, source_read_minutes: it.source_read_minutes }; - // Photos display full (cover); only wide/tall figures (diagrams) get the framed plate. + // News images are hotlinked from the source, so a single fetch can transiently + // fail (slow CDN, rate limit, hiccup) and leave a blank plate until you refresh. + // Probe with a couple of retries and reveal the photo only once it's truly loaded + // (and thus cached) — otherwise the typographic topic cover stays. The probe also + // tells us cover (photo) vs. framed plate (wide/tall figure) from real dimensions. if (news?.image) { - const probe = new Image(); - probe.onload = () => { - const a = probe.naturalWidth / probe.naturalHeight; - newsFit = a >= 0.85 && a <= 1.9 ? 'cover' : 'contain'; + const url = news.image; + let tries = 0; + const load = () => { + const probe = new Image(); + probe.onload = () => { + const a = probe.naturalWidth / probe.naturalHeight; + newsFit = a >= 0.85 && a <= 1.9 ? 'cover' : 'contain'; + newsImgOk = true; + }; + probe.onerror = () => { if (++tries <= 2) setTimeout(load, 500 * tries); }; + probe.src = url; }; - probe.src = news.image; + load(); } } catch { /* fall back to design copy */ } @@ -178,7 +190,7 @@