One thread everywhere
Your site and Bluesky always show the same public conversation.
Bluesky-native comments
Turn the replies to any Bluesky post into a comment section. No database, no account system, and no conversation locked to your website.
One public conversation
AT ProtocolJeremy @jvuillermet.eu
What if your website comments lived on Bluesky?
Replies stay visible there.
Your site and Bluesky always show the same public conversation.
Drop in the hosted iframe without building a database or API.
Use the isolated iframe or render the library directly on your origin.
Get started
<div
data-calque
data-post="https://bsky.app/profile/jvuillermet.eu/post/3mte65o7e622i"
data-title="Comments"
></div>
<script async src="https://calque.jvuillermet.eu/embed.js"></script>
<div id="comments"></div>
<script src="https://calque.jvuillermet.eu/embed.js"></script>
<script>
Calque.embed(
document.querySelector('#comments'),
{
post: 'https://bsky.app/profile/jvuillermet.eu/post/3mte65o7e622i',
title: 'Comments',
},
)
</script>
import Calque from 'calque'
Calque.configure({ oauth: false })
Calque.render(
document.querySelector('#comments'),
{
post: 'https://bsky.app/profile/jvuillermet.eu/post/3mte65o7e622i',
title: 'Comments',
},
)
<div id="comments"></div>
<script src="https://calque.jvuillermet.eu/calque.js"></script>
<script>
Calque.configure({ oauth: false })
Calque.render(
document.querySelector('#comments'),
{
post: 'https://bsky.app/profile/jvuillermet.eu/post/3mte65o7e622i',
},
)
</script>
OAuth requirements
Direct rendering keeps authentication in the page's origin. Serve an OAuth client metadata JSON file over HTTPS, then configure it before calling Calque.render().
client_id must exactly match the metadata URL.redirect_uris.atproto repo:app.bsky.feed.post?action=create.Calque.configure({
oauth: {
clientId: 'https://example.com/oauth-client-metadata.json',
display: 'popup',
},
})
Live example
Showing the playground defaults.
Readers join the thread here.