About Data & Portability Blog Featured Instances

Bluesky Comments Widget: Add replies to your site

Share your page link on Bluesky, then use this widget to show replies as comments on your site. No login or authentication needed.

Cover image for Bluesky Comments Widget: Add replies to your site

Integrate replies to a specific Bluesky post directly into your website or blog articles. This widget fetches the comment thread for a given post and displays it, allowing readers to see the conversation happening on Bluesky without leaving your site.

Features

  • Embed Bluesky Replies: Show the discussion from a Bluesky post thread with correct visual nesting.
  • Parent Post Stats: Displays likes, reposts, replies, and quotes for the original post (hides stats with zero count), linked to Bluesky where applicable.
  • No Authentication Required: Uses the public Bluesky API.
  • Simple Integration: Add a div and a small JavaScript snippet to your HTML.
  • Controls: Includes options to sort and search comments.
  • Clickable Comments: Entire comment bodies link back to the original reply post on Bluesky.
  • Customizable: Don't like the design? Style the widget using bluesky-comments.css.
  • Dependency: Uses Phosphor Icons (linked via CDN).

How to Use

  1. Get the Files: Download bluesky-comments.js and bluesky-comments.css. Place them in your website's project folder (e.g., js/ and css/).
  1. Link Files in HTML: In the <head> of your HTML, link the CSS files. Load bluesky-comments.css AFTER any general stylesheets (like style.css) if you encounter styling conflicts.
<head>
    <link rel="stylesheet" href="path/to/your/css/style.css"> <!-- Your general styles -->
    <link rel="stylesheet" href="path/to/your/css/bluesky-comments.css"> <!-- Widget styles -->
    <link rel="stylesheet" type="text/css" href="https://unpkg.com/@phosphor-icons/web@2.1.1/src/duotone/style.css" />
</head>

Before the closing </body> tag, link the JavaScript file:

<body>
    <script src="path/to/your/js/bluesky-comments.js"></script>
    <!-- Initialization script below -->
</body>

(Update path/to/your/css/ and path/to/your/js/)

  1. Add the Container: Place this empty div in your HTML where the comments should appear. Give it a unique ID.
<div id="my-bluesky-comments">
    <p><i>Loading Bluesky comments...</i></p>
</div>
  1. Initialize the Widget: Add the following <script> block after including bluesky-comments.js (usually just before </body>). Update targetContainerId and blueskyPostUri below.
<script>
    document.addEventListener('DOMContentLoaded', function () {
        const targetContainerId = 'my-bluesky-comments';
        const blueskyPostUri = 'at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/3lktlkvn2lc2k'; // <<<--- CHANGE THIS URI
        if (typeof loadAndRenderComments === 'function') {
            loadAndRenderComments(targetContainerId, blueskyPostUri);
        } else {
            console.error("Error: loadAndRenderComments function not found.");
            const container = document.getElementById(targetContainerId);
            if (container) {
                container.innerHTML = '<p class="bsky-comments-error">Error: Could not load comments component.</p>';
            }
        }
    });
</script>

Customization

  • Styling: Modify bluesky-comments.css (CSS variables are available at the top).
  • Behavior: Adjust constants like BSKY_MAX_INITIAL_COMMENTSBSKY_COMMENTS_INCREMENT, or BSKY_INDENT_SIZE_PX in bluesky-comments.js.

Dependencies

Sample HTML Template

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Bluesky Comments Widget Example</title>

    <!-- Link to the widget's CSS file (in the same directory) -->
    <link rel="stylesheet" href="bluesky-comments.css">

    <!-- Link to Google Fonts (optional, but used by the CSS) -->
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link
        href="https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap"
        rel="stylesheet">

    <!-- Link to Phosphor Icons CSS (required for icons) -->
    <link rel="stylesheet" type="text/css" href="https://unpkg.com/@phosphor-icons/web@2.1.1/src/duotone/style.css" />
</head>

<body>
    <div class="widget-wrapper">
        <div id="bluesky-comment-widget">
            <!-- Initial placeholder message -->
            <p><i>Loading Bluesky comments...</i></p>
        </div>
    </div>
    <!-- Include the widget's JavaScript file (in the same directory) -->
    <!-- IMPORTANT: Load this script AFTER the container div -->
    <script src="bluesky-comments.js"></script>
    <!-- Initialize the script -->
    <script>
        document.addEventListener('DOMContentLoaded', function () {
            // --- Configuration ---
            // 1. ID of the container div above. MUST match.
            const targetContainerId = 'bluesky-comment-widget';

            // 2. AT URI of the Bluesky post to display replies from.
            //    Find via post options (...) > Copy link to post > extract 'at://...' part.
            const blueskyPostUri = 'at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/3lktlkvn2lc2k';
            // 3. Load the comments.
            if (typeof loadAndRenderComments === 'function') {
                loadAndRenderComments(targetContainerId, blueskyPostUri);
            } else {
                console.error("Error: loadAndRenderComments function not found. Ensure bluesky-comments.js is loaded correctly and before this script block.");
                const container = document.getElementById(targetContainerId);
                if (container) {
                    container.innerHTML = '<p class="bsky-comments-error" style="padding:1em; text-align:center;">Error: Could not load comments component JavaScript.</p>';
                }
            }
        });
    </script>
</body>

</html>

I'm not a coder. I use LLMs like Claude, Mistral, Meta AI, ChatGPT, and Gemini to create things that fit what I need. I share them so others can use them too. The code may not follow standard rules, so if you're a developer and see ways to make it better, I'd really appreciate your help.