External Publication
Visit Post

Adding Bluesky Comments to an Astro Blog

~/.bnux April 17, 2026
Source

I've been wanting to add comments to this blog, but I didn't want to deal with a third-party comment system or manage a database. Then I realized I already have a place where people can discuss posts. Bluesky.

Bluesky's API is public and requires no auth for reading. So the idea is simple. Post about a blog entry on Bluesky, drop the post's AT URI into the frontmatter, and let a Vue component fetch the reply thread and render it as comments. No accounts to manage, no moderation tools to build, and the conversation lives where people are already hanging out.

How it works

When a blog post has a in its frontmatter, a Vue component loads on the page and calls the public Bluesky API to fetch the reply thread. Replies get sorted by likes and rendered with the author's avatar, handle, and timestamp. Each comment links back to the original post on Bluesky so people can jump in and reply directly.

The component uses Astro's directive, so it loads after the page is interactive and doesn't block the initial render.

Setting it up Add the field to the content schema

I added an optional string to the blog collection schema in . Build the component

The component takes a single prop (the AT URI) and does everything client-side.

The public API endpoint is . It accepts a parameter (the AT URI of the post) and a parameter (how many levels of replies to fetch). I'm fetching up to six levels deep so nested conversations can show up without needing another request. Wire it into the post layout

In , the component conditionally renders when the frontmatter includes a .

No env vars, no API keys, no server-side code. Automate the Bluesky post

I didn't want to manually copy AT URIs every time I publish, so I put together a small Node script that handles the round trip. It scans for blog posts missing a , creates a Bluesky post with the title and link, and writes the URI back into the frontmatter.

The script uses a Bluesky App Password for auth, passed in via environment variables ( and ). After running it, the frontmatter gets updated with the AT URI and I just commit and deploy. This post was published that way.

Domain as a Bluesky handle

While I was at it, I also set up as my Bluesky handle. Bluesky lets you verify a domain by adding a DNS TXT record.

A nice bit of identity verification that ties the blog and the Bluesky account together.

What I like about this approach

The conversation stays on Bluesky, which means I don't need to build moderation, authentication, or spam filtering. People comment using their existing accounts. And since the API is public, there's no server-side component to maintain.

If I forget to create a Bluesky post for something, the comment section just doesn't appear. Graceful degradation by default.

If you scroll down, you should see it in action :) Resources Bluesky API Documentation AT Protocol Specification Astro Client Directives

Discussion in the ATmosphere

Loading comments...