fix(social-activity): include boosts in Mastodon feed

@svemagie@indieweb.social's activity is primarily boosts, so
exclude_reblogs=true left mastodonFeed empty and the Mastodon tab
hidden. Remove that filter and resolve content/author/url from
status.reblog when the post is a boost. Add a "boosted from" label
in the widget for context.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
svemagie
2026-03-20 08:18:55 +01:00
parent c0fa51b84d
commit 9ff16cb032
2 changed files with 36 additions and 28 deletions
+33 -28
View File
@@ -43,8 +43,8 @@ export default async function () {
return []; return [];
} }
// Fetch recent statuses (excluding replies and boosts for cleaner feed) // Fetch recent statuses (excluding replies; boosts included since that's primary activity)
const statusesUrl = `https://${instance}/api/v1/accounts/${account.id}/statuses?limit=10&exclude_replies=true&exclude_reblogs=true`; const statusesUrl = `https://${instance}/api/v1/accounts/${account.id}/statuses?limit=10&exclude_replies=true`;
const statuses = await EleventyFetch(statusesUrl, { const statuses = await EleventyFetch(statusesUrl, {
duration: "15m", // Cache for 15 minutes duration: "15m", // Cache for 15 minutes
@@ -61,32 +61,37 @@ export default async function () {
return []; return [];
} }
// Transform statuses into a simpler format // Transform statuses into a simpler format; for boosts use the reblogged post's content
return statuses.map((status) => ({ return statuses.map((status) => {
id: status.id, const isBoost = !!status.reblog;
url: status.url, const source = isBoost ? status.reblog : status;
text: stripHtml(status.content), return {
htmlContent: status.content, id: status.id,
createdAt: status.created_at, url: source.url,
author: { text: stripHtml(source.content),
username: status.account.username, htmlContent: source.content,
displayName: status.account.display_name || status.account.username, createdAt: status.created_at,
avatar: status.account.avatar, isBoost,
url: status.account.url, author: {
}, username: source.account.username,
favouritesCount: status.favourites_count || 0, displayName: source.account.display_name || source.account.username,
reblogsCount: status.reblogs_count || 0, avatar: source.account.avatar,
repliesCount: status.replies_count || 0, url: source.account.url,
// Media attachments },
media: status.media_attachments favouritesCount: source.favourites_count || 0,
? status.media_attachments.map((m) => ({ reblogsCount: source.reblogs_count || 0,
type: m.type, repliesCount: source.replies_count || 0,
url: m.url, // Media attachments
previewUrl: m.preview_url, media: source.media_attachments
description: m.description, ? source.media_attachments.map((m) => ({
})) type: m.type,
: [], url: m.url,
})); previewUrl: m.preview_url,
description: m.description,
}))
: [],
};
});
} catch (error) { } catch (error) {
console.error("Error fetching Mastodon feed:", error.message); console.error("Error fetching Mastodon feed:", error.message);
return []; return [];
@@ -96,6 +96,9 @@
{% for post in mastodonFeed | head(5) %} {% for post in mastodonFeed | head(5) %}
<li class="border-b border-surface-200 dark:border-surface-700 pb-3 last:border-0"> <li class="border-b border-surface-200 dark:border-surface-700 pb-3 last:border-0">
<a href="{{ post.url }}" target="_blank" rel="noopener" class="block group"> <a href="{{ post.url }}" target="_blank" rel="noopener" class="block group">
{% if post.isBoost %}
<p class="text-xs text-surface-500 dark:text-surface-400 mb-1">boosted from @{{ post.author.username }}</p>
{% endif %}
<p class="text-sm text-surface-700 dark:text-surface-300 group-hover:text-[#a730b8] transition-colors"> <p class="text-sm text-surface-700 dark:text-surface-300 group-hover:text-[#a730b8] transition-colors">
{{ post.text | truncate(140) }} {{ post.text | truncate(140) }}
</p> </p>