Fun with Bluesky and Websockets
Tags: Websockets Bluesky JavaScript WebDev
Do you remember the good old days when we used to have complete free-for-all access to the Twitter API? Oh, those were the days. I remember making so many different projects that used the API in some way or another and thinking how great it was. Sadly, those days are very much behind us (thanks, Elon), but the good news is — there’s an alternative.
But that doesn’t matter any more because, as I’m sure you’ve already heard, there’s a new microblogging platform on the block and its name is Bluesky — the decentralised version of X / Twitter! And yes, there’s also Mastodon and Nostr, but those two haven’t taken off in quite the same way as Bluesky has. Bluesky has a lot going for it, but the most exciting part of the platform is the AT Protocol (the tech that makes decentralisation on Bluesky possible) and its ability to stream activity via a Firehose.
Bluesky offers access to this service via a convenient tool known as Jetstream, which is essentially a JSON-friendly interface for streaming the Firehose using WebSocket technology. Now, when I found out about this service, I couldn’t resist using it for a simple side project — after all, the WebSocket is freely accessible to the web. I’d never worked with WebSockets before, so I saw this as an opportunity to learn more about how they work while using the Bluesky Firehose as a fun data source to play with. Turns out, they’re really easy to work with.
So with this in mind, I made a simple front-end app with some basic JavaScript (and a little help from D3.js) for streaming discussion threads and new follower connections as social networks, which evolve in real time. Feel free to see for yourself or check out the demos below.
The follow network streams new follower connections as they occur in real time, plotted as an interactive graph. This is complemented by some simple stats, displaying the number of users and new followers since loading the page. It’s surprising to me just how many connections are made in such a short amount of time. It also goes to show just how interconnected users are on Bluesky. Very quickly, you can see hubs of accounts starting to emerge.
As well as followers, you can also view discussion threads as they appear in real time too. The benefit of this approach is that you can monitor conversations as they happen, filtering down to specific keywords if needed. In this case, a node on the graph represents a reply, and an edge represents who the reply is directed to.
I found these really fun to build and to watch — but let’s unpack the tools that made all this possible.
As I said before, this app uses JavaScript WebSockets for streaming data from Bluesky. There are four Jetstream endpoints you can access to stream data:
jetstream1.us-east.bsky.network
jetstream2.us-east.bsky.network
jetstream1.us-west.bsky.network
jetstream2.us-west.bsky.network
Once you’ve picked the appropriate endpoint for your needs (e.g. the nearest location), you can begin streaming data with a little JavaScript magic:
const socket = new WebSocket("wss://jetstream1.us-east.bsky.network/subscribe");
socket.addEventListener("open", (event) => {
console.log("Jetstream connection opened:", event);
});
// Handle errors
socket.addEventListener("error", (error) => {
console.error("WebSocket error:", error);
});
// Handle connection close
socket.addEventListener("close", (event) => {
console.log("WebSocket connection closed:", event);
});
// Handle data message
socket.addEventListener("message", (event) => {
console.log("WebSocket message received:", event);
// Convert to JSON
let data = JSON.parse(event.data);
});
It’s as simple as that. Don’t forget the /subscribe
path in the URL — it’s very important and has caught me off guard a few times.
By default, this will process every activity from the network. If you want to learn more about how this works and how you can filter data down to specific sets, check out this fantastic post by Jake Lazaroff, where he goes into more detail using collections.