Adding Bluesky-powered comments to any website in five minutes

Long live the open web!

I used to have comments on my website—powered by Disqus. Then I learned that Disqus is hostile, slow and bad for privacy, so I got rid of them.

But I miss having a comments section!

It’s fun to see what people have to say about something I’ve written, and Hacker News or Twitter / X never really felt the same as having something directly on my own website.

So when I saw this post today about how you can use Bluesky to add a comments section to your blog, I got excited.

also, any replies in this thread will appear as comments on the blog post itself. made possible by the aforementioned Open Network 🫡 ft. @shreyanjain.net's reply below

[image or embed]

— Emily (@emilyliu.me) November 25, 2024 at 1:58 AM

Maybe I could back my comments section, but this time on top of Bluesky’s open network?

I grabbed the gist of the provided code from Emily’s blog about how it works, then used Cursor and Claude to help me:

  1. Rip out the Next.js dependencies.
  2. Convert it from Tailwind to native CSS.
  3. Integrate it into my own site (on Jekyll)

Within less than 30 minutes I had a proof of concept running on my local machine. Cool!

After getting this far, I decided it would be nice to publish it as an npm package so that anyone can use it without having to go through the same steps I did. So I just did that!

Now you can install the bluesky-comments package and create an instant Bluesky-powered comments section on your own site!

Here’s an example of how I added it to my site—which is built on Jekyll.

First you need to add the default styles the page <head> somewhere in a base template:

<link rel="stylesheet" href="https://unpkg.com/bluesky-comments@0.8.0/dist/bluesky-comments.css">

Then you need to add an import map for the React dependencies in the end of the body on any page that you want to show comments on:

<script type="importmap">
{
  "imports": {
    "react": "https://esm.sh/react@18",
    "react-dom": "https://esm.sh/react-dom@18"
  }
}
</script>

Finally, import and initialize the comments by passing in a link to the post you want to use as a base:

<script type="module">
  import {BlueskyComments} from 'https://unpkg.com/bluesky-comments@0.8.0/dist/bluesky-comments.es.js';

  document.addEventListener('DOMContentLoaded', function() {
    const uri = 'https://bsky.app/profile/coryzue.com/post/3lbrko5zsgk24';
    const author = 'coryzue.com';
    BlueskyComments.init('bluesky-comments', {
      uri,
      author,
      commentFilters: [BlueskyComments.Filters.NoPins],
    });
  });
</script>

This will search for comments in two places:

  1. If there is a bluesky_post_uri in the Jekyll front matter it will use that.
  2. If not, it will check my account for any links to that page, and use the post with the most likes.

And voila, instant comments section!

Here’s an example of the Jekyll front matter for this post:

---
layout: post
title:  "Adding Bluesky-powered comments to any website in five minutes"
excerpt: "Long live the open web!"
bluesky_post_uri: "https://bsky.app/profile/coryzue.com/post/3lbrko5zsgk24"
---

Of course, if you’re using a different blogging platform you can pass the post link variable in however you prefer, or just rely on the auto-discovery.

The source code for the package can be found here.

Let me know in the comments below if you have any feedback! And hopefully they work…

Update November 26

Addded support for automatic post-linking based on the author parameter.

Update December 4

Updated the import syntax and APIs to use ES modules. Also added the ability to filter posts (see the example above, which filters out responses that consist only of the “📌” emoji).

Update December 11

Added support and documentation for using the library in a React project.

First install the package:

npm install bluesky-comments

Then you can use the library in your projects by importing the CSS and components:

import 'bluesky-comments/bluesky-comments.css'
import { CommentSection } from "bluesky-comments";

And using them in a React component like this:

function App() {
  return (
    <>
      <div>Comments Will Display Below</div>
        <CommentSection
           author="coryzue.com"
           uri=""
           onEmpty={() => <div>No comments yet</div>}
           commentFilters={[]} />
      </div>
    </>
  )
}