bluesky-comments-tag is a JavaScript SDK for building applications with Bluesky and AT Protocol.
A lightweight, customizable web component to use Bluesky for your website comments.
Load the script from a CDN and then use the tag in your HTML:
<!-- Use the element -->
<bluesky-comments url="https://bsky.app/profile/mk.gg/post/3lb3cxyeh3c2f">
</bluesky-comments>
<!-- Include the script tag anywhere -->
<script type="module">
import "https://esm.sh/bluesky-comments-tag/load";
</script>
The component can be customized in two ways:
bluesky-comments {
/* Colors */
--bluesky-text-color: #333;
--bluesky-handle-color: #888;
--bluesky-footer-text-color: rgb(111, 134, 159);
--bluesky-bg-color: #fff;
--bluesky-hover-bg: #f0f0f0;
--bluesky-border-color: #e0e0e0;
/* Typography */
--bluesky-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
"Helvetica Neue", Arial, sans-serif;
--bluesky-font-size: 14px;
--bluesky-footer-font-size: 14px;
}
@media (prefers-color-scheme: dark) {
bluesky-comments {
--bluesky-bg-color: #1e293b;
--bluesky-text-color: #e2e8f0;
--bluesky-border-color: #4a5568;
--bluesky-hover-bg: #2d3748;
--bluesky-handle-color: #9ca3af;
--bluesky-footer-text-color: #9ca3af;
}
}
The component exposes several parts that can be styled directly using the ::part()
selector:
bluesky-comments::part(avatar) {
border: 2px solid gold;
}
bluesky-comments::part(comment-header) {
background: #f8f9fa;
}
bluesky-comments::part(comment-body) {
font-size: 1.1em;
}
bluesky-comments::part(comment-content) {
line-height: 1.6;
}
bluesky-comments::part(comment-footer) {
padding: 8px 12px;
}
Available parts:
avatar
- The user's avatar image or default avatarcomment-header
- The header section containing avatar and user infocomment-body
- The main comment content containercomment-content
- The text content of the commentcomment-footer
- The footer with interaction countsProperty | Default | Description |
---|---|---|
--bluesky-font-family | -apple-system, etc. | Font family for all text |
--bluesky-font-size | 16px | Base font size |
--bluesky-text-color | #333 | Main text color |
--bluesky-handle-color | #888 | Username/handle color |
--bluesky-footer-text-color | rgb(111, 134, 159) | Footer text color |
--bluesky-bg-color | #fff | Background color |
--bluesky-hover-bg | #f0f0f0 | Hover state background |
--bluesky-border-color | #e0e0e0 | Border color |
--bluesky-spacing-xs | 5px | Extra small spacing |
--bluesky-spacing-sm | 8px | Small spacing |
--bluesky-spacing-md | 10px | Medium spacing |
--bluesky-spacing-lg | 15px | Large spacing |
--bluesky-avatar-size | 24px | Size of avatar images |
--bluesky-avatar-bg | #e0e0e0 | Default avatar background |
--bluesky-reply-border-width | 2px | Reply border width |
--bluesky-footer-font-size | 15px | Footer text size |
--bluesky-icon-size | 18px | Size of footer icons |
Take these with a pinch of salt: Claude made them up. You can use these as a starting point for your own custom themes.
bluesky-comments {
--bluesky-bg-color: #ffffff;
--bluesky-font-family: "Inter", system-ui, sans-serif;
--bluesky-font-size: 15px;
--bluesky-text-color: #1a2b3c;
--bluesky-handle-color: #64748b;
--bluesky-footer-text-color: #94a3b8;
--bluesky-border-color: #e2e8f0;
--bluesky-hover-bg: #f8fafc;
--bluesky-spacing-xs: 8px;
--bluesky-spacing-sm: 12px;
--bluesky-spacing-md: 16px;
--bluesky-avatar-size: 40px;
--bluesky-avatar-bg: #f1f5f9;
--bluesky-reply-border-width: 2px;
--bluesky-footer-font-size: 13px;
--bluesky-icon-size: 16px;
}
/* Optional: Enhanced styling using parts */
bluesky-comments::part(avatar) {
border: 2px solid #fff;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}
bluesky-comments::part(comment-content) {
line-height: 1.6;
}
bluesky-comments {
--bluesky-bg-color: #fcfcfc;
--bluesky-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
sans-serif;
--bluesky-font-size: 14px;
--bluesky-text-color: #2c3e50;
--bluesky-handle-color: #718096;
--bluesky-footer-text-color: #a0aec0;
--bluesky-border-color: #edf2f7;
--bluesky-hover-bg: #f7fafc;
--bluesky-spacing-xs: 6px;
--bluesky-spacing-sm: 10px;
--bluesky-spacing-md: 12px;
--bluesky-avatar-size: 32px;
--bluesky-avatar-bg: #edf2f7;
--bluesky-reply-border-width: 1px;
--bluesky-footer-font-size: 12px;
--bluesky-icon-size: 14px;
}
bluesky-comments::part(comment-header) {
padding: 8px 12px;
background: #f8fafc;
border-radius: 4px 4px 0 0;
}
bluesky-comments {
--bluesky-bg-color: #1e1e2e;
--bluesky-font-family: system-ui, sans-serif;
--bluesky-font-size: 14px;
--bluesky-text-color: #cdd6f4;
--bluesky-handle-color: #a6adc8;
--bluesky-footer-text-color: #7f849c;
--bluesky-border-color: #313244;
--bluesky-hover-bg: #181825;
--bluesky-spacing-xs: 6px;
--bluesky-spacing-sm: 10px;
--bluesky-spacing-md: 14px;
--bluesky-avatar-size: 36px;
--bluesky-avatar-bg: #313244;
--bluesky-reply-border-width: 1px;
--bluesky-footer-font-size: 13px;
--bluesky-icon-size: 16px;
}
bluesky-comments::part(comment-header) {
background: rgba(49, 50, 68, 0.5);
}
bluesky-comments::part(avatar) {
border: 1px solid #45475a;
}
bluesky-comments {
--bluesky-bg-color: #ffffff;
--bluesky-font-family: Verdana, arial, helvetica, sans-serif;
--bluesky-font-size: 13px;
--bluesky-text-color: #1c1c1c;
--bluesky-handle-color: #787c7e;
--bluesky-footer-text-color: #787c7e;
--bluesky-border-color: #edeff1;
--bluesky-hover-bg: #f6f7f8;
--bluesky-spacing-xs: 4px;
--bluesky-spacing-sm: 6px;
--bluesky-spacing-md: 8px;
--bluesky-avatar-size: 24px;
--bluesky-avatar-bg: #edeff1;
--bluesky-reply-border-width: 2px;
--bluesky-footer-font-size: 12px;
--bluesky-icon-size: 16px;
}
bluesky-comments::part(comment-content) {
line-height: 1.5;
padding: 4px 0;
}
bluesky-comments::part(comment-footer) {
opacity: 0.8;
}
bluesky-comments {
--bluesky-bg-color: #fffef9;
--bluesky-font-family: Georgia, "Times New Roman", serif;
--bluesky-font-size: 16px;
--bluesky-text-color: #2d3436;
--bluesky-handle-color: #636e72;
--bluesky-footer-text-color: #b2bec3;
--bluesky-border-color: #dfe6e9;
--bluesky-hover-bg: #f5f6fa;
--bluesky-spacing-xs: 8px;
--bluesky-spacing-sm: 12px;
--bluesky-spacing-md: 20px;
--bluesky-avatar-size: 48px;
--bluesky-avatar-bg: #dfe6e9;
--bluesky-reply-border-width: 1px;
--bluesky-footer-font-size: 14px;
--bluesky-icon-size: 18px;
}
bluesky-comments::part(comment-content) {
line-height: 1.7;
letter-spacing: 0.2px;
}
bluesky-comments::part(avatar) {
border-radius: 8px;
}
Did you get "HTMLElement is not defined" error? Make sure you are loading the component in the browser, not in SSR or Node.js. This is a client-only component.
The component uses standard web components and modern JavaScript features.
Contributions are welcome! Please feel free to submit a Pull Request.
MIT License - feel free to use this component in your projects.
a collection of lightweight TypeScript packages for AT Protocol, the protocol powering Bluesky.
Use this repository to get started with your own Bluesky Labeler.
ATProto Feed Generator Starter Kit
AT Protocol Reference Implementation (TypeScript)
A dead simple client for subscribing to an ATProto Relay ("firehose").
A fully typed client for the Bluesky Jetstream (https://github.com/bluesky-social/jetstream) service.
Your Brand Here!
50K+ engaged viewers every month
Limited spots available!
📧 Contact us via email🦋 Contact us on Bluesky