Source feeds: click a source to see its publication feed

Click a source name on any card → a feed of just that source's articles,
newest-first, still accepted / non-duplicate / boundary-filtered (the calm
promise isn't bypassed). A natural way to follow a publication's feel.

* queries.feed + /api/feed: source_id filter; Article output gains source_id.
* Frontend: source label is a button → transient 'source:<id>' view (like
  'tag:<slug>'), rendered in the feed grid with Load more, header = source name.
* Ad-hoc, not a pinned lane. Foundation for a future source page (metadata) +
  Follow; shareable /source/<slug> route and source_view analytics come then.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
jay
2026-06-08 08:30:33 -04:00
parent 50dc2167cd
commit 38889f76e5
5 changed files with 55 additions and 8 deletions
+13 -2
View File
@@ -2,7 +2,7 @@
import { auth, savedIds, toggleSave } from '$lib/auth.svelte.js';
import { track } from '$lib/analytics.js';
let { article, onaction, onreplace, ontag, onimageerror, onview, hero = false, thumb = false } = $props();
let { article, onaction, onreplace, ontag, onsource, onimageerror, onview, hero = false, thumb = false } = $props();
function opened() {
// Records history; the /a page itself fires the summary_viewed event on load.
@@ -122,7 +122,13 @@
{/each}
</div>
</div>
<div class="src">{article.source}</div>
<div class="src">
{#if onsource && article.source_id}
<button type="button" class="srclink" onclick={() => onsource(article.source_id, article.source)}>{article.source}</button>
{:else}
{article.source}
{/if}
</div>
<h3><a href={summaryHref} onclick={opened}>{article.title}</a></h3>
@@ -217,6 +223,11 @@
.tile .pillrow { align-self: center; }
/* Source on its own line below the tags, left-justified, for uniformity. */
.src { color: var(--muted); font-size: 0.78rem; margin: -2px 0 2px; }
.srclink {
background: none; border: none; padding: 0; font: inherit; color: var(--muted);
cursor: pointer; border-bottom: 1px dotted transparent;
}
.srclink:hover { color: var(--accent-deep); border-bottom-color: var(--accent-soft); }
h3 { font-size: 1.18rem; }
h3 a:hover { color: var(--accent-deep); }