Liked https://sugardave.cloud/posts/astro/using-live-collection-for-webmentions
Astro's Live Content Collection - Display Webmentions ๐
Today I would like to speak about a new experimental feature available in Astro 5.10 and beyond: live content collections. A live content collection allows you to fetch its data at runtime rather than build time, which is how a regular content collection would normally be used.
Content Collections
A well-known use case for a content collection is retrieving all the blog posts you have written and then rendering the matching post based on path processing in a โslug pageโ. Anyone who has gone through the complete โBuild your first Astro Blogโ tutorial should be familiar with how that works.
When running your Astro site in static mode, this requires all potential post paths to be either manually specified in the slug page or dynamically built using the getStaticPaths
method. In either case, these paths are created at build time and cannot be changed afterwards. This is also true when you use server-side rendering (SSR), but the method for matching a path to a post is slightly different and not part of the goal of this post.
The important thing to realize is that all โregularโ content collections need to have their matching paths resolved at build time for static sites and all the content must be present at build time when using either static builds or SSR.
Live Content Collections
With live content collections, developers can take more control over how they obtain content for rendering. One thing you cannot do with regular content collections is have them fetch their data on-demand when a page is requested. Live content collections enable this.
For this site, I have been slowly integrating bits and pieces of interesting concepts from the IndieWeb. One of these is โwebmentionsโ. Without going into too much detail, webmentions are based on microformats and enable disparate, unconnected sites and services to โmentionโ your content and for your site to be able to discover those mentions and process them how you see fit.
Implementation
I am using a custom content loader to fetch webmentions from Webmention.io. I call it webmentionLoader
because that seems appropriate. I have defined a Webmention
interface based on suggestions from Claude Sonnet 4. This is a naive first pass, so Iโm only going to show the parts that I actually needed to get this all to work:
export interface Webmention {
// Core webmention properties
id: string;
source: string; // URL of the page that mentions your content
target: string; // URL of your content being mentioned
targetPath: string; // Path of the target URL (for easier filtering)
...
}
I also have a helper function to retrieve the webmentions for my domain. An API key is generated for each site you add to Webmention.io.
const getMentionsHTML = async (apiKey: string) => {
const response = await fetch(
`https://webmention.io/api/mentions.html?token=${apiKey}`
);
if (!response.ok) {
throw new Error(`Failed to fetch webmentions: ${response.statusText}`);
}
return response.text();
};
The actual live content loader function needs to return an object with three required properties:
name
: a string to represent the name of the loaderloadCollection
: an async function that will return the entire collection of data or a filtered setloadEntry
: an async function that will return a single item in the collection based on a filter
Since I want to customize the display of webmention data, I am using JSDOM
to parse the HTML returned from the fetch in loadCollection
. Another thing to note is that since webmentions are a many-to-one relation with posts, loadEntry
will never be used, so I am only returning an error indicating it is not supported.
export const webmentionLoader = ({
apiKey
}: {
apiKey: string;
}): LiveLoader<Webmention> => {
return {
name: 'webmention-loader',
loadCollection: async ({filter}) => {
const {targetPath} = filter || {targetPath: ''};
try {
const webmentions: Webmention[] = await getMentionsHTML(apiKey).then(
(html) => {
const dom = new JSDOM(html);
const doc = dom.window.document;
const mentions = Array.from(
doc.querySelectorAll('.h-entry.mention')
);
const items = mentions.map((element, index) => {
// construct a target path from the target URL
const target = element
.querySelector('.u-mention-of')
?.getAttribute('href') as string;
const postPath = target ? new URL(target).pathname : '';
return {
id: `${postPath}:${index}`,
data: {
author: {
name: element.querySelector('.p-author')
?.textContent as string
}
},
source: element
.querySelector('.u-url')
?.getAttribute('href') as string,
target,
targetPath: postPath
};
});
if (targetPath) {
// Filter by targetPath if provided
return items.filter((item) => item.targetPath === targetPath);
}
return items;
}
);
return {
entries: webmentions.map((mention) => ({
id: mention.id,
data: mention
}))
};
} catch (error) {
return {
error: new Error(
`Failed to retrieve webmentions: ${error instanceof Error ? error.message : 'Unknown error'}`
)
};
}
},
// there can be multiple webmentions for the same target, so we will never use loadEntry
loadEntry: async () => {
return {
error: new Error(`webmentionLoader does not support loadEntry`)
};
}
};
};
Now, in my slug page I can handle blog posts as a regular content collection just like Iโve been doing and also grab any webmentions that match them.
---
import type {CollectionEntry} from 'astro:content';
import type {LiveDataEntry} from 'astro';
import type {Webmention} from '@lib/webmentionLoader';
import {getCollection, getLiveCollection, render} from 'astro:content';
import MarkdownPostLayout from '@layouts/MarkdownPostLayout.astro';
interface Props {
post: CollectionEntry<'blog'>;
postMentions: LiveDataEntry<Webmention>[];
}
const {
params: {slug},
url
} = Astro;
const currentPath = url.pathname.endsWith('/')
? url.pathname.slice(0, -1)
: url.pathname;
const [post] = (await getCollection('blog', ({id}) => {
return id === slug || id.startsWith(`${slug}/`);
})) as Props['post'][];
const frontmatter = post?.data;
const {entries: webmentions, error} = await getLiveCollection('webmentions', {
targetPath: currentPath
});
const postMentions: Props['postMentions'] = [];
if (error) {
console.error(`Error fetching webmentions:, ${error}`);
} else if (webmentions && webmentions.length > 0) {
postMentions.push(
...(webmentions as LiveDataEntry<Webmention>[]).filter((mention) => {
const {source, target} = mention.data;
if (!target || !source) {
return false;
}
try {
const targetUrl = new URL(target);
return targetUrl.pathname === currentPath;
} catch {
return target === currentPath;
}
})
);
}
let Content;
if (post) {
({Content} = await render(post));
}
export const prerender = false;
---
<MarkdownPostLayout
frontmatter={frontmatter ?? {}}
mentions={postMentions.map((m) => m.data)}
>
{Content && <Content />}
</MarkdownPostLayout>
It may be a little messy, but it gets the job done. If you want to see it in action, why not link to this page from your site and submit a mention to the handy manual submission form? The source URL
will be the page where you linked to this page and the target URL
will be this page. After a successful submission, reload this page and you should see it displayed above the footer. Hopefully ๐
Wrapping Up
After putting it all together, I can now retrieve and display webmentions associated with any blog post on sugardave.cloud, huzzah! In the future, I hope to implement other appropriate webmention collections for my posts. My next target is the u-in-reply-to
type so I can see what others think about my posts. Once I have that, I am sure I will have another blog post about that journey.
Liked https://briefs.video/videos/introducing-webbed-sites/
Introducing: Webbed Sites
Liked https://tilde.zone/@xandra/114547017410429628
alexandra (@[email protected])
Liked https://dbushell.com/2025/05/07/glossary-web-component/
Glossary Web Component
Ive added a secret glossary to my blog! You might find it by hovering over special links. Dont tell anyone, its a secret. At least until I can find a way to style the links without them being a distraction. Do I need to, or can they remain
The Idea
This project came about when I noted concern over my reliance on
The Implementation
I write my blog posts in
[React](/glossary/react.json)
This references a
{
"title": "React",
"description": "A legacy JavaScript framework (turned religion). Favoured by tech bros and famous for bloated bundles and crippling web performance.",
"links": [
{
"name": "JSX.lol",
"title": "Does anybody actually like React?",
"url": "https://jsx.lol"
},
{
"name": "React",
"url": "https://react.dev"
}
]
}
My build script replaces the markdown link with a
<glossary-term id="--term-react">
<a href="https://jsx.lol">React</a>
</glossary-term>
The first link in the JSON is used as the canonical source.
HTML wrapped in a <glossary-term>
element is enhanced with a fancy popover.
If youve missed every example so far here is the
I captured a screen recording of how it should appear:
The popover is activated by either hover or keyboard focus. The escape key can also dismiss them. For touchscreens Im going to test that live&
[INSERT TEST RESULTS]
Test results: it works fine. If youve got one of those new Apple Pencils the new new one, not the new old one the hover effect is magical. Touch taps are taken straight to the canonical link. The popover might be open upon return. Maybe I should cancel the popover based on touch events to avoid confusion?
Failures
Initially I tried to use
I really tried. It left me in tears and I rage quit. It might be the most unintuitive, doesnt work like it says, infuriating web standard ever. When anchoring a popover
its impossible to ensure elements stay inside the viewport (without JavaScript). Please prove me wrong!
I tried to get creative with allow-discrete
and @starting-style
and failed. In an isolated demo its all gravy but together this new CSS stuff doesnt plays nice. Its not all
CSS anchors are Chrome and
Ultimately I gave up and used
I dont plan to immediately retrofit older blog posts with glossary links. Although that could be a quick find & replace if Im careful. Im looking for positive feedback before I do. So let me know if you like it (or not). If no one hates it Ill plough ahead, because I like it. This glossary may just be the third incarnation of my bookmarks blog.
Im tempted to use a similar technique to create popover cards for linked notes. They have more content so I need to consider that more.
Liked https://hachyderm.io/@charliewilco/114435540754888601
Charlie ๏ฟฝ (@[email protected])
Liked https://mastodon.social/@davatron5000/114379441761385823
Dave Rupert (@[email protected])
Liked https://velvetshark.com/ai-company-logos-that-look-like-buttholes
Why do AI company logos look like buttholes?

If you pay attention to AI company branding, you'll notice a pattern:
- Circular shape (often with a gradient)
- Central opening or focal point
- Radiating elements from the center
- Soft, organic curves
Sound familiar? It should, because it's also an apt description of... well, you know.
A butthole.
The circular AI logo epidemic
If you ever thought that AI company logos look like buttholes, you're not alone.
FastCompany noticed this trend in 2023 and published an article about it, but (I could only presume) their editors and lawyers didn't let them title the article the way the wanted it to title, so it got published with a more safe for work title: The AI boom is creating a new logo trend: the swirling hexagon. They also were careful not to mention anything anatomical.
I don't have editors or lawyers, so let's take a closer look at some examples:
OpenAI's logo evolution

OpenAI's original logo was a simple, text-based mark. Then came the redesign: a perfect circle with a subtle gradient and central void.
OpenAI's official explanation is a masterclass in corporate euphemism:
"The Blossom logo is more than just a visual symbol; it represents the core philosophy that guides our approach to design and innovation. At its heart, the logo captures the dynamic intersection between humanity and technologytwo forces that shape our world and inspire our work. The design embodies the fluidity and warmth of human-centered thinking through the use of circles, while right angles introduce the precision and structure that technology demands."
Sure, Sam.
Translation: "We made a circular shape with some angles because it looked nice, then wrote flowery language to justify why our butthole-adjacent design is actually profound."
The fluidity and warmth of human-centered thinking through the use of circles is perhaps the most elegant way anyone has ever described making a logo that resembles an anus.
The Big AI companies

Looking at the logos of the Big AI companies, you can see that they almost all of them have a circular or snowflake-like shape and a central opening.
Only DeepSeek and DeepMind don't follow the trend. Interestingly, both are sea-related.
Smoking gun: Anthropic's Claude
Up until this point, the logos have been subtle. You might say that the logos are simply circular and there's not much more to it.
But Anthropic's Claude takes it to the next level.
Here's a side-by-side comparison with a drawing from Kurt Vonnegut's book "Breakfast of Champions". I added Claude's logo below for easy comparison.

Both the drawing and the description in the book are unambiguous. This is not just "a circular shape with a gradient" anymore, is it?
It's not just AI companies
Even traditional companies aren't immune. Here are a few notable or funny examples. But the percentage of AI company logos that look like buttholes is still significanly higher than than any other industry.

I especially like the Electrolux one. It's simple, memorable, and once you see a butt and bikini, you can't unsee it.
Why does this keep happening?
There are several factors at play:
Circular design psychology
Circles represent wholeness, completion, and infinityconcepts that align with AI's promise. They're also friendly and non-threatening, qualities companies desperately want to project when selling potentially job-replacing technology.
Unintentional biomimicry

The human brain finds familiar patterns in random shapes (pareidolia), like a face on Mars, taken by the Viking 1 orbiter and released by NASA in 1976.
But sometimes, designers inadvertently recreate biological forms without realizing the... anatomical implications.
The copycat effect
Once a few major players adopted the circular sphincter aesthetic, everyone followed suit. Now we have an industry where standing out means looking exactly like everyone else's butthole.
Basically, the same reason why so many brands change their logos and look like everyone else.

Design by committee
Another factor is how these logos are created. Important corporate decisions involve many stakeholders. The result is often the safest, most inoffensive option, the average of everyone's opinions. In design meetings at AI companies, conversations probably sound like:
- Can we make it more futuristic?
- It needs to feel advanced but approachable.
- Let's add a subtle gradient to convey intelligence.
No single person suggests making a logo that resembles an anus, but when everyone's feedback gets incorporated, that's what often emerges. Risk aversion in corporate environments naturally pushes designs toward familiar, "safe" territory, which apparently means anatomical openings.
What this says about tech branding
This phenomenon reveals something deeper about the tech industry: the fear of standing out too much. Despite claims of innovation and disruption, there's tremendous pressure to look legitimate by conforming to established visual language.
When OpenAI's sphincter-like logo became successful, it created a template that said, "This is what serious AI looks like." Now, any new AI company that doesn't resemble a colorful anatomical opening risks being seen as unserious or unprofessional.
Tech design trends through history
This isn't the first time tech design has gone through a conformity phase. Consider these previous waves:
- 1990s-2000s: 3D and Glossy - Remember when every logo needed a drop shadow and a glassy shine? Apple's aqua interface set the standard.
- 2010-2013: Skeuomorphism - Digital designs mimicking physical objects, with stitched leather textures and realistic dials.
- 2013-2018: Flat Design - Reaction to skeuomorphism brought minimal, clean interfaces with bright colors and no shadows.
- 2018-2022: Neomorphism - Soft shadows and semi-flat design creating subtle, "touchable" interfaces.
- 2022-Present: The Butthole Era - Circular gradients with central focal points dominating AI branding.
Each era started with innovations that were quickly copied until the industry reached saturation point and moved on to the next trend.

Logos become increasingly interchangeable (one of the bags is real, but they all look the same)
Historic logo disasters: You're not alone
AI companies can take some comfort in knowing they're not the first to face unintended anatomical comparisons. Logo history is filled with disasters but to keep this consistent with the theme of the article, here's a couple of them.

- Zune logo, when flipped, says something different. Maybe that's one of the reasons why iPod won?
- Brazilian Institute of Oriental Studies is a stylized pagoda sillhouetted against the setting sun. Or so the designers wanted it to look. The final result was much more... anatomical. They since changed it to something less suggestive.
Maybe companies should have a panel of "middle schoolers" on their payroll to review logos before launch. They'll find every possible inappropriate interpretation with ruthless efficiency.
Breaking free from the butthole
For companies brave enough to differentiate, here are some alternatives:
- Embrace sharp angles - geometric shapes with defined edges create a distinct visual identity
- Use negative space creatively - think FedEx arrow, not biological openings
- Avoid radial symmetry - not everything needs to be perfectly circular
- Skip the gradient - flat design still works
- Test with diverse audiences - if five different people independently say "that looks like a butthole," it probably does (show it to teenagers if you want to uncover even the most subtle anatomical implications)
Conclusion
Does this mean AI companies should change their branding? Not necessarily. The familiarity clearly works in building trust. But perhaps the next wave of AI innovation could be accompanied by some visual innovation too.
For companies looking to break the mold, consider these approaches that successful tech brands have used:
- Embrace meaningful abstraction - Slack's hashtag-inspired logo communicates collaboration without circular clich�s
- Leverage letterforms - Netflix's simple "N" has become instantly recognizable without anatomical confusion
- Tell a story - Stripe's distinctive parallel lines reflect payment flows moving seamlessly
- Use distinctive color combinations - Twitch's purple branding stands out in a sea of blue tech logos
The challenge for the next generation of AI companies isn't just technological - it's finding visual language that communicates innovation without resorting to the same tired sphincter-inspired patterns.
PS. This post is meant to be humorous, but let's not pretend there isn't a serious point here about the depressing sameness in modern design. No actual anuses were consulted during this research, though several designers were clearly thinking about them.
Liked https://mastodon.social/@owa/114199424779247989
Open Web Advocacy (@[email protected])
Liked https://fediverse.zachleat.com/@zachleat/114072799841101889