Roscoe Rubin-Rottenberg 0:05 Hi, I'm Roscoe. 0:08 I'm 16 years old. 0:10 I live in Brooklyn, New York, and I am the co-founder and CTO of Spark Social. 0:18 Spark is Spark is a short-form video platform for @protocol, and we've been thinking over the past months about how to properly interoperate with other platforms on @protocol. 0:43 So this talk is just a few findings and conclusions that we have from these experiences. 0:53 And 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. 1:08 Podcasts are interesting because all podcasts aren't just on well-known podcast platforms like Apple Podcasts, Spotify, and the late Google Podcasts. 1:22 Podcasts are also on apps no one knows about, like Podbean, Anchor, and Pocket Casts. 1:31 This is possible because podcasts are just RSS feeds. 1:35 People submit their podcasts to large apps, and those apps have their own registries. 1:42 But smaller apps can make registries or pull from multiple open registries like the one that Apple Podcasts has. 1:53 This is an example of interoperability. 1:56 And because of it, the phrase "wherever you get your podcasts" has been coined. 2:02 The reason you can say this, and it's so simple, is because podcasts are just one thing. 2:08 You can get in many different places. 2:11 This is not the case for @protocol. 2:15 Because with podcasts, it's just RSS feeds with a little header at the top. 2:21 On @protocol, there are a ton of different record types. 2:27 And now I'm sure there are hundreds of record types, and these are called lexicons. 2:34 They define the schema and the shape of a record. 2:39 And everything on that protocol is a record. 2:44 So your posts, your likes, everything, they're all different lexicons on your repo. 2:55 Now, we're not going to talk about all lexicons. 2:59 We're going to— group it into, uh, two different categories: graph and content. 3:07 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. 3:21 So a like would not count as graph because it's applied to a post, but a follow would. 3:26 Because it's applied to a user. 3:29 And content is a much looser definition of just the thing that people view on the app. 3:37 So generally independent content that isn't linking to anything. 3:45 First, we're going to talk about follows. 3:49 Now right now there are about 5 or 6 follows on the protocol. 3:55 There's Bluesky, Spark, Tangled, Grain, and now Semble. 4:00 And Semble is a little bit of a sneak because it can also be applied to publications, not just people. 4:09 But we'll let it slide. 4:12 So all of these are basically the exact same schema with the exception of assemble. 4:20 So why not just have one lexicon for all of them if they're all the same? 4:25 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. 4:36 And it makes sense because this seems to be the closest parallel to where— listen to this podcast wherever you get your podcasts. 4:45 It's "follow me wherever you get your social media" or something along those lines. 4:52 Now, there have been existing standardization efforts like StandardSite and LexiconCommunity. 4:58 StandardSite is for publications. 5:01 LexiconCommunity is for miscellaneous and has mostly been used for events thus far. 5:07 But neither of them tackle any graph lexicons and not follows. 5:14 So should we standardize follows? 5:17 Well, yes and no, because there are a lot of users who want multiple social graphs on different platforms. 5:25 You can imagine watching a Twitch streamer play video games but not wanting to see their political takes on Twitter. 5:34 And the same is true for @protocol apps like Streamplace and blue sky. 5:40 Uh, and this is why I think even when apps launch companion apps, they often keep their follows separate. 5:50 When Instagram launched Threads, they didn't carry over your follows from Instagram to Threads. 5:55 But there are many users who are asking for one persistent social graph. 6:03 So Should we let users choose? 6:07 Well, let's try it. 6:10 So we have a user who can make Spark follows and they can make Bluesky follows. 6:18 And in order to decide which one they should use on the app to let them choose between a consistent follow across platforms and one follow for each one, we'll make a preference to indicate which of these they're using for the Spark app. 6:43 So because the preference can be changed at any time, even if the user chooses Spark follows, we need to still consume Bluesky follows. 6:53 Uh, 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. 7:12 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. 7:28 Uh, and for aggregate counts that have to be done so many times, this gets expensive and slow. 7:36 Uh, and there's a reason that you often see counts on Bluesky that aren't necessarily accurate. 7:42 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. 7:58 They might have other reasons for that, but we'll assume for the sake of argument that that is the case. 8:07 So this gets very complicated. 8:11 And the other reason this is not ideal is that you're scaling for users you don't have. 8:21 The follows, well, they're nice and as Rudy said in his talk, users will complain if the counts aren't accurate. 8:31 They don't really enhance the experience of using your app in a meaningful way. 8:37 It's just a count next to a username. 8:41 And follows are 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. 8:55 And all this scaling kind of seems pointless because at this point we're not really helping the user experience of our app. 9:03 We're just doing interoperability for interoperability's sake. 9:06 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. 9:27 And it doesn't help the user experience enough to justify it. 9:32 So what is @protocol for? 9:35 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. 9:53 And it's a nice way to pitch the protocol because it applies to both PDS migrations and moving between apps. 10:01 If you have a common follow lexicon and common graph lexicons. 10:07 And it's very simple, but it doesn't hold up in practice. 10:17 So I think the best way to interoperate between app protocol apps is with the actual content that is on the apps. 10:28 And there are way more types of content than there are types of follows. 10:33 Here are a few of them. 10:34 There are Bluesky posts, Tangled repos, POP feed reviews, and Leaflet comments. 10:41 And content is something that apps already interoperate between. 10:45 Specifically, I know Spark and Leaflet both supplement their own comments for Bluesky comments. 10:53 Spark filters for replies to the cross-post record of a post, and Leaflet filters for embeds with a Leaflet URL of a document. 11:03 Uh, now we can take this one step further and say that we're going to use Blue Sky posts not just to supplement comments or replies, but also to supplement the actual main content of an app. 11:23 So there are way more Bluesky posts than there are Spark videos. 11:29 So Spark could theoretically consume into their app view Bluesky posts where the embed is a video. 11:38 And here we have a much better deal because scaling benefits all users. 11:43 Even if we're consuming a video from a user who doesn't use our app, we are still benefiting the users that can see and watch that video. 11:55 And the experience is enhanced for all users of your app. 12:02 And it increases the amount of content on your app. 12:07 And this can be done very simply in apps because unlike things like follows, 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 a ton of complicated SQL queries between the two. 12:43 So I feel like it seems obvious that any app who wants to interoperate should do it between the content of their app, right? 12:53 Except if you do that, you will burn in hell forever. 13:01 Because now we have to come back and talk about blocks. 13:08 Blocks are very interesting because let's say we are the Spark app and we are consuming a Blue Sky post made by Jerry. 13:26 Now, if we want to be a good citizen of the atmosphere and respect blocks, then we will also consume, in addition to app.bsky.feed.posts that have video fields, we will also consume all app.bsky.graph.blocks. 13:49 And we will check if any of those match Jerry. 13:53 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. 14:03 But we also have to check app.bsky.graph.listBlocks. 14:09 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. 14:26 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 mindspace that if they block someone on Bluesky, even if they're able to interact with that person on a different atmosphere app, they are at the very least not able to see their Bluesky posts or Bluesky content. 15:12 So that's a social contract with the user that is pretty important. 15:17 And I think being a good citizen of the atmosphere means respecting that. 15:22 So I think even if we don't necessarily need follow, a universal follow lexicon, we do need a universal block lexicon. 15:32 Because to achieve the remixability and dynamic, energy of the atmosphere that so many talks this weekend have 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. 16:10 And I think many people ask, like, we have all these skeuomorphic experiences to previous apps that came before @protocol, but what is an @proto-native experience? 16:26 What is the experience that is @proto-specific? 16:31 And I think it is that. 16:33 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. 16:48 I think that remixability and much of the stuff that Dan Abramov 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. 17:09 And if you would like to make a common block system for yourself, Graph.social is only $8,000. 17:20 So, Peter Wang, hit me up. 17:29 My germ DMs are open. 17:35 So at Spark, we did the opposite of what I think we should have done, which is we started with ingesting blue sky follows, and then blocks, and then feed generators, and then we were eventually going to do posts. 17:54 If you are doing interoperability, I think you should go in the opposite direction. 18:01 And I think these lessons— our detour with interoperability with Blue Sky led to no concrete features because we scrapped it because we learned all of this. 18:18 And it took multiple months off the Spark timeline. 18:23 So, uh, we want to make it easier for other apps to interoperate. 18:30 Uh, and we want the Atmosphere to be a place where interoperability is front and center. 18:38 Uh, Spark was launched, uh, with OpenSocial at the core, built fundamentally on @protocol. 18:47 In January, we entered open beta, and now that open beta today is available on the App Store. 18:59 Thank you. 19:04 And I'm excited to announce that as of today, Spark is fully open source. 19:18 So you can find that right now at github.com/sparksocial and later today or potentially later this week on Tangled. 19:34 And you can find all of that and download the app at spark.so. 19:39 Thank you. 19:40 Thank you, Roscoe. 19:42 Let's give him a round of applause. 19:50 Cool.