Footer HTML
<script>
if (document.querySelector("article")?.classList.contains("h-entry")) {
async function fetchInteractions() {
try {
const res = await fetch(
"https://webmention.io/api/mentions.jf2?target=" +
encodeURIComponent(location.href)
);
const data = await res.json();
if (!data?.children?.length) return;
const likes = [];
const reposts = [];
const replies = [];
const mentions = [];
data.children.forEach(child => {
const authorUrl = child.author?.url || child["wm-source"] || "#";
const authorPhoto = child.author?.photo || "https://via.placeholder.com/50";
function createAvatar(emoji = null) {
const wrapper = document.createElement("div");
wrapper.className = "avatar-container";
const avatarLink = document.createElement("a");
avatarLink.href = authorUrl;
avatarLink.target = "_blank";
avatarLink.rel = "nofollow noopener";
const img = document.createElement("img");
img.src = authorPhoto;
img.className = "webmention-avatar";
avatarLink.appendChild(img);
wrapper.appendChild(avatarLink);
if (emoji) {
const badge = document.createElement("span");
badge.className = "avatar-emoji";
badge.textContent = emoji;
wrapper.appendChild(badge);
}
return wrapper;
}
switch (child["wm-property"]) {
case "like-of":
likes.push(createAvatar("❤️"));
break;
case "repost-of":
reposts.push(createAvatar("🔁"));
break;
case "in-reply-to":
const reply = document.createElement("div");
reply.className = "webmention-reply";
reply.appendChild(createAvatar("💬"));
if (child.content?.text) {
const quote = document.createElement("blockquote");
quote.textContent = child.content.text;
reply.appendChild(quote);
}
replies.push(reply);
break;
case "mention-of":
const link = document.createElement("a");
link.href = child["wm-source"];
link.target = "_blank";
link.rel = "nofollow noopener";
link.textContent = child["wm-source"];
mentions.push(link);
break;
}
});
const wrapper = document.createElement("div");
wrapper.className = "webmentions";
const details = document.createElement("details");
if (replies.length) details.open = true;
const summary = document.createElement("summary");
// wrap the emoji + counts in a span
summary.innerHTML = `IndieWeb Interactions <span class="counts">❤️ ${likes.length} 🔁 ${reposts.length} 💬 ${replies.length} ✍️ ${mentions.length}</span>`;
details.appendChild(summary);
const reactionsRow = document.createElement("div");
reactionsRow.className = "reactions-row";
likes.forEach(a => reactionsRow.appendChild(a));
reposts.forEach(a => reactionsRow.appendChild(a));
details.appendChild(reactionsRow);
if (replies.length) {
const repliesContainer = document.createElement("div");
repliesContainer.className = "replies-section";
replies.forEach(r => repliesContainer.appendChild(r));
details.appendChild(repliesContainer);
}
if (mentions.length) {
const mentionsHeading = document.createElement("p");
mentionsHeading.textContent = "✍️ Mentions";
details.appendChild(mentionsHeading);
const ul = document.createElement("ul");
mentions.forEach(m => {
const li = document.createElement("li");
li.appendChild(m);
ul.appendChild(li);
});
details.appendChild(ul);
}
wrapper.appendChild(details);
const postNav = document.querySelector("div.post-nav");
if (postNav) postNav.parentNode.insertBefore(wrapper, postNav.nextSibling);
} catch (err) {
console.warn("Webmentions failed", err);
}
}
fetchInteractions();
}
</script>