← All Talks
Presentation Development and Protocol

Wherever You Get Your Podcasts: Interoperability in the Atmosphere

Roscoe Rubin-Rottenberg · @knotbin.com
Sunday, March 29, 2026
4:30 PM – 5:00 PM PT
Great Hall South
Available in-person & via livestream — Stream 1 (Great Hall South)

Connecting the "Wherever You Get Your Podcasts" blog I posted a ~month ago (https://knotbin.leaflet.pub/3lx3uqveyj22f) to interoperability in atproto.m using the podcast metaphor for feature adoption & how they're just one type of RSS feed, just like lexicons with records. In theory, apps can implement any lexicon. I'd then go into the actual experience of implementing this at the huge scale of Bluesky's lexicon and why Spark decided to take a different approach to lexicon interop in the end.

Hi. I'm Roscoe. I'm 16 years old. I live in Brooklyn, New York, and I am the co-founder and CTO of Spark Social. Spark is Spark is a short form video platform for AT Protocol. And we've been thinking over the past months about how to properly interoperate with other platforms on AT Protocol. So this talk is just a few findings and conclusions that we have from these experiences. Now I'll talk more about what we actually did and the experiments we tried, but first I want to take a brief detour to talk about podcasts. Podcasts are interesting because all podcasts aren't just on well-known podcast platforms like Apple Podcasts, Spotify, and the late Google Podcasts.

Podcasts are also on apps no one knows about, like Podbean Anchor, and Pocket Casts. This is possible because podcasts are just RSS feeds. People submit their podcasts to large apps, and those apps have their own registries, but smaller apps can make registries or pull from multiple open registries like the one that Apple Podcasts has. This is an example of interoperability. And because of it, the phrase wherever you get your podcasts has been coined. The reason you can say this, and it's so simple, is because podcasts are just one thing that you can get in many different places.

This is not the case for AT Protocol. Because with podcasts, it's just RSS feeds with a little header at the top. On AT Protocol, there are a ton of different record types. And now I'm sure there are hundreds of record types, and these are called lexicons. They define the schema and the shape of a record, and everything on AT Protocol is a record. So your posts, your likes, everything. They're all different lexicons on your repo. Now we're not going to talk about all lexicons. We're going to group it into uh two different categories. Graph and content.

Now, graph contains things like follows and blocks, and we're defining it as any record that is applied to another user, not a record that they make. So a like would not count as graph because it's applied to a post, but a follow would because it's applied to a user. And content is a much looser definition of just the thing that people view on the app. So generally independent content that isn't linking to anything. First, we're going to talk about follows. Now right now there are about five or six follows on the protocol. There's Bluesky, Spark, Tangled, Grain, and now Semble.

And Semble is a little bit of a sneak because it can also be applied to publications, not just people, but we'll let it slide. So all of these are basically the exact same schema, with the exception of Semble. So why not just have one lexicon for all of them if they're all the same? And I'm only being facetious here because this was how I thought this should be solved and how we tried to solve it at Spark. And it makes sense because this seems to be the closest parallel to where listen to this podcast wherever you get your podcasts.

It's follow me wherever you get your social media or something along those lines. Now there have been existing standardization efforts like standard site and lexicon community, uh, standard site is for publications, lexicon communities for miscellaneous, and has mostly been used for events thus far. But neither of them tackle any graph lexicons and not follows. So should we standardize follows? Well, yes and no, because there are a lot of users who want multiple social graphs on different platforms. You can imagine watching a Twitch streamer play video games but not wanting to see their political takes on Twitter.

And the same is true for AT Protocol apps like Streamplace and Bluesky. And this is why I think even when apps launch companion apps, they often keep their follows separate. When Instagram launched threads, they didn't carry over your follows from Instagram to threads. But there are many users who are asking for one persistent social graph. So should we let users choose? Well, let's try it. So we have a user who can make Spark follows and they can make Bluesky follows.

So because the preference can be changed at any time, even if the user chooses Spark follows, we need to still consume Bluesky follows. Now it's easy to use this for following counts to get how many users this example user is following, because we just query what the preference says and then we fetch all the records of that type. But to get the amount of users that follow them, it's much more complicated because for every user that follows that has a follow record, we have to go query their preference. And for aggregate counts that have to be done so many times, this gets expensive and slow.

And there's a reason that you often see counts on Bluesky that aren't necessarily accurate, like you'll see one follower and you click in and there aren't any. Because Bluesky doesn't check for blocks or takedowns or moderation action against users because checks like this slow the app down so much, I assume. They might have other reasons for that, but uh we'll assume for the sake of argument that that is the case. This gets very complicated, and the other reason this is not ideal is that you're scaling for users you don't have. They are like follows, well, they're nice, and as Rudy said in his talk, users will complain if the counts aren't accurate.

They don't really enhance the experience of using your app in a meaningful way. Uh it's just a count next to a username. Uh and follows are, as far as I know, the second most common type of record. So you're gonna get a lot of them, and you're gonna have to scale to store all of them. And all this scaling kind of seems pointless because at this point we're not really helping the user experience of our app. We're just doing interoperability for interoperability's sake. Uh because this isn't really something that even if users are asking to be able to choose between their follows.

As far as I know, that demand isn't great enough to justify all this complexity, and it doesn't help the user experience enough to justify it. So what is AT Protocol for? Like in a real way, this is something that developers in the community kind of cling to as a way to pitch the protocol and a way to describe the protocol is a persistent social graph. And it's a nice way to pitch the protocol because it applies to both PDS migrations and moving between apps if you have a common follow lexicon and common graph lexicons. And it's very simple, but it doesn't hold up in practice.

So I think the best way to interoperate between app protocol apps is with the actual content that is on the apps. And there are way more types of content than there are types of follows.

And content is something that apps already interoperate between.

Now we can take this one step further and say that we're going to use Bluesky posts not just to supplement comments or replies, but also to supplement the actual main content of uh app. Uh so there are way more Bluesky posts than there are Spark videos, so Spark could theoretically consume into their app view, Bluesky posts where the embed is a video. And here we have a much better deal because scaling benefits all users. Even if we're consuming uh video from a user who doesn't use our app, we are still benefiting the users that can see and watch that video and the experience is enhanced for all users of your app.

Uh and it increases the amount of content on your app. Uh and this can be done very simply in apps uh because unlike things like follows uh you don't have to have very complicated aggregate counts and you can separate the content that you're interoperating with from your app's main content and keep your infrastructure very nice and maintainable and not have to worry about uh a ton of complicated uh SQL queries between the two. Uh so I feel like it seems obvious that any app who wants to interoperate should do it between the content of their app, right?

Uh except if you do that, you will burn in hell forever. Uh because now we have to come back and talk about blocks. Uh blocks are very interesting because let's say we are the Spark app and we are consuming a Bluesky post made by Jerry. Uh now if we want to resp be a good citizen of the Atmosphere and respect blocks, uh then we will also consume in addition to app.b sky.feed.posts that have video fields, we will also consume uh all app.b sky.graph.blocks. And we will check if any of those match Jerry, and if any of those do, and it's the viewer of the post or the person Jerry is making the post about, we will not show the post.

Uh but we also have to check app.b sky.graph.list blocks. And if we're doing list blocks, we also have to consume the list and all its list items and check if any of those list items are applied to Jerry and if the viewer is subscribed to that list with a list block. Uh this is very complicated. And it makes it so when we just want to get to consume one post by Jerry that has a video in it and show it to our users, we have to change our entire server structure to match Blue Sky's block system because the user is in the mind space that if they block someone on Bluesky, even if they're able to interact with that person on a different admit Atmosphere app, they are at the very least not able to see their Bluesky posts or Bluesky content.

So that's a social contract with the user that is pretty important, and I think being a good citizen of the Atmosphere means respecting that. So I think even if we don't necessarily need follow a universal follow lexicon, we do need a universal block lexicon because to achieve the remixability and dynamic uh energy of the Atmosphere that so many talks this weekend have uh described, and I think is the way the Atmosphere will be best utilized, then we can't make it so that every time you want to interoperate with a new app, you have to also interoperate with their block system or whatever system they have for hiding content from users.

And I think many people ask like we have all these skewomorphic experiences to previous apps that came before AT Protocol, but what is an atproto native experience? What is the experience that is atproto specific? And I think it is that it is the remixability and apps that bring together so much different types of content that all different types of people have made and not necessarily intended to be used in that way. I think that remixability and much of the stuff that Dan Abermov was showing off earlier today is how the Atmosphere is best used, and in order to do that, we need to have some common standards, and that includes blocks.

And if you would like to make a common block system for yourself, graph.social is only eight thousand dollars. Uh so uh Peter Wang hit me up. My germ DMs are open. Uh so at Spark, we did the opposite of what I think we should have done, which is we started with ingesting Bluesky follows and then blocks and then feed generators, and then we were eventually going to do posts. Uh and if you are doing interoperability, I think you should go in the opposite direction. Uh and I think these lessons uh our detour with interoperability with Bluesky led to no concrete features because we scrapped it because we learned all of this.

Uh and it took multiple months off the Spark timeline. So uh we want to make it easier for other apps to interoperate, uh, and we want the Atmosphere to be a place where interoperability is front and center. Uh Spark was launched uh with open social at the core built fundamentally on AT Protocol. Uh in January, we entered open beta uh and now that open beta today is available on the app store. Uh thank you. And I'm excited to announce that as of today, Spark is fully open source.

So you can find that right now at GitHub.com slash sparks social and later today or potentially later this week on Tangled. And you can find all of that and download the app at spark.so. Thank you. Thank you, Roscoe.