From e3e6f24753450dcd8276b40f8f0398c9e97c8e37 Mon Sep 17 00:00:00 2001 From: jay Date: Fri, 26 Jun 2026 22:05:41 -0400 Subject: [PATCH] home3 news: typographic category cover for pictureless articles ~half the brief has no image, leaving a blank well above the headline. When an article has no image_url, fill the well with the topic word (e.g. "science") in lowercase Newsreader on a soft topic-tinted field, color-coded per topic (science/tech/environment/health/community/culture/world/space + neutral default). Same 5:4 footprint as the photo, so card height stays consistent. Threads `topic` through the news object. Co-Authored-By: Claude Opus 4.8 --- frontend/src/routes/home3/+page.svelte | 39 ++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/frontend/src/routes/home3/+page.svelte b/frontend/src/routes/home3/+page.svelte index bc3c2e7..7889479 100644 --- a/frontend/src/routes/home3/+page.svelte +++ b/frontend/src/routes/home3/+page.svelte @@ -6,9 +6,24 @@ // /home3 — the Claude Design "Frame A" direction (editorial, with colour), rebuilt in // our codebase with our real logo + self-hosted fonts, wired to live data. Hidden // prototype (noindex), alongside /home2 so we can compare. - let news = $state(null); // {id, title, summary, image} + 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 + + // 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. + const TOPIC_TINT = { + science: { bg: '#e2edf1', ink: '#2f6d86' }, + technology: { bg: '#e8e9f4', ink: '#5a5fa0' }, + environment: { bg: '#e6efe2', ink: '#3a7d5b' }, + health: { bg: '#f4e8e8', ink: '#a8566a' }, + community: { bg: '#f3ece0', ink: '#a9763f' }, + culture: { bg: '#ece5f3', ink: '#7e51b0' }, + world: { bg: '#e6ecf3', ink: '#4a6da0' }, + space: { bg: '#e7e7f2', ink: '#4a4e8a' }, + }; + const TOPIC_DEFAULT = { bg: '#e6edef', ink: '#3f6378' }; + let topicTint = $derived(TOPIC_TINT[(news?.topic || '').toLowerCase()] || TOPIC_DEFAULT); let word = $state(null); // /api/word/today let quote = $state(null); // /api/quote/today let fact = $state(null); // /api/onthisday/today @@ -91,7 +106,7 @@ } catch { /* global brief */ } try { const it = (await getJSON(`/api/brief?limit=1${homeq}`))?.items?.[0]; - if (it) news = { id: it.id, title: it.title, summary: it.summary || it.description || '', image: it.image_url || null, source_read_minutes: it.source_read_minutes }; + 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. if (news?.image) { const probe = new Image(); @@ -159,9 +174,16 @@
-
-
-
+ {#if news?.image} +
+
+
+ {:else} + +
+ {news?.topic || 'good news'} +
+ {/if}
GOOD NEWS @@ -371,6 +393,13 @@ box-shadow: 0 6px 18px -10px rgba(30, 60, 70, 0.28); background-size: contain; background-origin: content-box; } + /* pictureless fallback: topic word on a soft topic-tinted field, same footprint as the photo */ + .news-typo { aspect-ratio: 5/4; display: flex; align-items: center; justify-content: center; padding: 16px; box-sizing: border-box; } + .news-typo-word { + font-family: 'Newsreader', Georgia, serif; font-weight: 500; font-size: clamp(1.9rem, 5vw, 2.9rem); + line-height: 1.05; letter-spacing: -0.01em; text-transform: lowercase; text-align: center; max-width: 100%; + } + .news-body { padding: 24px 26px; flex: 1; display: flex; flex-direction: column; } .news h2 { font-size: clamp(1.55rem, 2.6vw, 30px); line-height: 1.14; margin: 12px 0 0;