我在我的博客上添加了一个Bluesky评论区。
I added a Bluesky comment section to my blog

原始链接: https://micahcantor.com/blog/bluesky-comment-section.html

## Bluesky 评论现已上线! 这篇博客现在配备了由 Bluesky 提供支持的评论区!作者之前一直避免使用评论区,因为维护动态服务需要付出很多精力。然而,受到 Cory Zue 的工作启发,他们直接将 Bluesky 回复嵌入到博客文章中,利用 Bluesky 的基础设施进行托管、审核和帐户验证。 作者选择 Bluesky 而不是 Twitter、Disqus 或 GitHub Discussions 等替代方案,是因为它具有开放、去中心化的特性(基于 AT Proto 构建),并且非常适合作为专门的社交平台。虽然最初计划允许从该网站发布内容,但构建完整的 Bluesky 客户端的复杂性导致了更简单、只读的实现方式。 该系统通过将每篇文章链接到特定的 Bluesky 帖子,并使用 Bluesky API 和 `react-query` 库获取/显示回复来工作。该实现大约 200 行代码,优先考虑简单性,仅提取回复中的文本内容,并使用基本的缩进进行线程显示。 如果感兴趣的人足够多,作者可能会考虑将他们的代码发布为软件包,但他们认为该实现的简单性使其易于复制。他们鼓励读者直接在 Bluesky 上继续讨论。

## Bluesky评论在博客上的应用:总结 Micah Cantor在他的博客上添加了一个Bluesky评论区,引发了Hacker News上关于静态网站评论系统替代方案的讨论。 许多用户分享了他们自己的方法,强调了对控制权的渴望以及避免依赖中心化平台的需求。 一种流行的做法是通过电子邮件或其他方式接受评论,手动审查垃圾邮件,然后将它们作为内容文件添加到网站的源代码中。 这确保了对评论的完全控制,并消除了供应商锁定。 其他人则利用Giscus(与GitHub Discussions结合)或利用Cloudflare Workers和静态站点生成器的自定义解决方案。 人们对审核提出了担忧,特别是关于欧盟反仇恨言论法律以及潜在的垃圾邮件问题。 讨论的解决方案包括利用Bluesky的审核功能(隐藏回复)和实施自定义标签。 对话还涉及了易用性(如Disqus)和自托管之间的权衡,一些人提倡使用去中心化协议,如ATProto(Bluesky)和Nostr。 最终,理想的解决方案取决于个人需求和技术专长。
相关文章

原文

Published on

You can now view replies to this blog post made on Bluesky directly on this website. Check it out here!

I've always wanted to host a comment section on my site, but it's difficult because the content is statically generated and hosted on a CDN. I could host comments on a separate VPS or cloud service. But maintaining a dynamic web service like this can be expensive and time-consuming — in general, I'm not interested in being an unpaid, part-time DevOps engineer.

Recently, however, I read a blog post by Cory Zue about how he embedded a comment section from Bluesky on his blog. I immediately understood to benefits of this approach. With this approach, Bluesky could handle all of the difficult work involved in managing a social media like account verification, hosting, storage, spam, and moderation. Meanwhile because Bluesky is an open platform with a public API, it's easy to directly embed comments on my own site.

There are other services that could be used for this purpose instead. Notably, I could embed replies from the social media formerly known as Twitter. Or I could use a platform like Disqus or even giscus, which hosts comments on GitHub Discussions. But I see Bluesky as a clearly superior choice among these options. For one, Bluesky is built on top of an open social media platform in AT Proto, meaning it can't easily be taken over by an authoritarian billionaire creep. Moreover, Bluesky is a full-fledged social media platform, which naturally makes it a better option for hosting a conversation than GitHub.

Zue published a standalone package called bluesky-comments that allows embedding comments in a React component as he did. But I decided to build this feature myself instead. Mainly this is because I wanted to make a few styling changes anyway to match the rest of my site. But I also wanted to leave the option open to adding more features in the future, which would be easier to do if I wrote the code myself. The entire implementation is small regardless, amounting to only ~200 LOC between the UI components and API functions.

Initially, I planned to allow people to directly post on Bluesky via my site. This would work by providing an OAuth flow that gives my site permission to post on Bluesky on behalf of the user. I actually did get the auth flow working, but building out a UI for posting and replying to existing comments is difficult to do well. Going down this path quickly leads to building what is essentially a custom Bluesky client, which I didn't have the time or interest in doing right now. Moreover, because the user needs to go through the auth flow and sign-in to their Bluesky account, the process is not really much easier than posting directly on a linked Bluesky post.

Without the requirement of allowing others to directly post on my site, the implementation became much simpler. Essentially, my task was to specify a Bluesky post that corresponds to the article in the site's metadata. Then, when the page loads I fetch the replies to that post from Bluesky, parse the response, and display the results in a simple comment section UI.

As explained in my last post, this site is built using React Server Components and Parcel. The content of my articles are written using MDX, an extension to Markdown that allows directly embedding JavaScript and JSX. In each post, I export a metadata object that I validate using a Zod schema. For instance, the metadata for this post looks like this:

export const metadata = {

title: "I added a Bluesky comment section to my blog",

description:

"How I embedded Bluesky replies directly on my site",

date: "2026-01-24",

bskyPostId: <post-id>,

tags: ["web-dev"],

};

The value of bskyPostId references the Bluesky post from which I'll pull replies to display in the comment section. Because my project is built in TypeScript, it was easy to integrate with the Bluesky TypeScript SDK (@bluesky/api on NPM). Reading the Bluesky API documentation and Zue's implementation led me to the getPostThread endpoint. Given an AT Protocol URI, this endpoint returns an object with data on the given post and its replies.

I could have interacted directly with the Bluesky API from my React component using fetch and useEffect. However, it can be a bit tricky to correctly handle loading and a error states, even for a simple feature like this. Because of this, I decided to use the Tanstack react-query package to manage the API request/response cycle. This library takes care of the messy work of handling errors, retries, and loading states while I simply provide it a function to fetch the post data.

Once I obtain the Bluesky response, the next task is parsing out the content and metadata for the replies. Bluesky supports a rich content structure in its posts for representing markup, references, and attachments. Building out a UI that fully respects this rich content would be difficult. Instead, I decided to keep it simple by just pulling out the text content from each reply.

Even so, building a UI that properly displays threaded comments, particularly one that is formatted well on small mobile devices, can be tricky. For now, my approach was to again keep it simple. I indented each reply and added a left border to make it easier to follow reply threads. Otherwise, I mostly copied design elements for layout of the profile picture and post date from Bluesky.

Lastly, I added a UI component linking to the parent post on Bluesky, and encouraging people to add to the conversation there. With this, the read-only comment section implementation was complete. If there's interest, I could publish my version of Bluesky comments as a standalone package. But several of the choices I made were relatively specific to my own site. Moreover, the implementation is simple enough that others could probably build their own version from reading the source code, just as I did using Zue's version.

Let me know what you think by replying on Bluesky. Hopefully this can help increase engagement with my blog posts, but then again, my last article generated no replies, so maybe not 😭.

联系我们 contact @ memedata.com