feat(blog): comment count badge on post overview
Deploy / verify (push) Successful in 38s
Deploy / deploy (push) Successful in 59s

PostCard now shows a small comment-count pill in the top-left of the
image when count > 0. BlogOverview bulk-fetches counts for the visible
posts via the new `/api/comments/counts?ids=…` endpoint and passes
them down. One request per page render, regardless of card count.

- New helper `getCommentCounts()` in `cms.ts`
- `BlogOverview.svelte` derives slugs from posts, fires bulk fetch
  in `$effect`, hands the result map to `PostCard`
- `PostCard.svelte` accepts `commentCount?: number | null`, renders
  pill only when value is a positive number

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Peter Meier
2026-04-28 13:26:09 +02:00
parent 8f45094f64
commit 8f791ebc54
3 changed files with 89 additions and 0 deletions
+31
View File
@@ -693,3 +693,34 @@ export async function getCalendarItems(
return data.items ?? [];
});
}
/**
* Bulk-fetches approved comment counts for many page_ids in one request.
* Hits the comment plugin's `/api/comments/counts` endpoint. Returns a map
* `{ pageId → count }` with `0` for any id missing in the response.
*
* The comment-plugin endpoints live behind a different env (`PUBLIC_CMS_URL`)
* and may be on a different origin in dev. SSR-side calls always hit it
* directly; the cookie sync of the visitor session does NOT happen here
* (counts are public anyway).
*/
export async function getCommentCounts(
pageIds: string[],
options?: { environment?: string },
): Promise<Record<string, number>> {
if (pageIds.length === 0) return {};
const base = getBaseUrl();
const url = new URL(`${base}/api/comments/counts`);
url.searchParams.set("ids", pageIds.join(","));
if (options?.environment) {
url.searchParams.set("_environment", options.environment);
}
try {
const res = await fetch(url.toString());
if (!res.ok) return {};
const data = (await res.json()) as { counts?: Record<string, number> };
return data.counts ?? {};
} catch {
return {};
}
}