<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Steve Klabnik — ATProto &amp; Bluesky</title><description>Bluesky, the AT Protocol, and decentralized social networking.</description><link>https://steveklabnik.com/</link><item><title>Too many words about DIDs</title><link>https://steveklabnik.com/writing/too-many-words-about-dids/</link><guid isPermaLink="true">https://steveklabnik.com/writing/too-many-words-about-dids/</guid><description>Your “Bluesky account” is not just a Bluesky account: it is an account that can be used with a variety of other applications. This post is going to be an exploration of part of what that means from a technical perspective, so if you’re not a software developer, this post isn’t…</description><pubDate>Tue, 14 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Your “Bluesky account” is not &lt;em&gt;just&lt;/em&gt; a Bluesky account: it is an account that
can be used with a variety of other applications. This post is going to be an
exploration of part of what that means from a technical perspective, so if you’re
not a software developer, this post isn’t for you. But what I’m going to explain
is the technical mechanism for how your account works separate from Bluesky, and
in fact, separate from any particular app.&lt;/p&gt;
&lt;p&gt;Let’s talk about identity: who are you, anyway? Users of a system need some sort
of way to describe who they are to use it. If you want to log in, you need to
present who you are. If you want to make a post, well, we need to know who the
author of that post is. For atproto, the protocol that underlies Bluesky and
other apps in the ATmosphere, they use the “Decentralized Identity” standard,
also known as DID. The &lt;a href=&quot;https://www.w3.org/TR/did-1.0/&quot;&gt;W3C standardized DIDs in
2022&lt;/a&gt;. As you might guess from the name, DIDs
are, an identifier that you can use as the basis of identity for building
applications. And the idea is that these identifiers are decentralized. However,
a lot of people have a lot of feelings about that specific word, and often
accuse atproto of not being properly decentralized. We’re going to go over the
details so you can understand how this works, and you can decide for yourself if
this approach suits you or not.&lt;/p&gt;
&lt;h2 id=&quot;dids-and-did-documents&quot;&gt;DIDs and DID Documents&lt;/h2&gt;
&lt;p&gt;Here is my DID, we’ll use this as an example: &lt;code&gt;did:plc:3danwc67lo7obz2fmdg6jxcr&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;There are three parts, separated by colons: The scheme (&lt;code&gt;did&lt;/code&gt;), the method (&lt;code&gt;plc&lt;/code&gt;),
and the DID method-specific identifier (&lt;code&gt;3danwc67lo7obz2fmdg6jxcr&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;To use a DID, such as &lt;code&gt;did:plc:3danwc67lo7obz2fmdg6jxcr&lt;/code&gt;, you resolve it into a
&lt;a href=&quot;https://www.w3.org/TR/did-1.0/#dfn-did-documents&quot;&gt;DID Document&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A set of data describing the DID subject, including mechanisms, such as
cryptographic public keys, that the DID subject or a DID delegate can use to
authenticate itself and prove its association with the DID.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That document contains &lt;a href=&quot;https://www.w3.org/TR/did-1.0/#core-properties&quot;&gt;various
properties&lt;/a&gt; that describe the
identity. Here’s my DID Document, at the time of writing:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &amp;quot;@context&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &amp;quot;https://www.w3.org/ns/did/v1&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &amp;quot;https://w3id.org/security/multikey/v1&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &amp;quot;https://w3id.org/security/suites/secp256k1-2019/v1&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &amp;quot;id&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;did:plc:3danwc67lo7obz2fmdg6jxcr&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &amp;quot;alsoKnownAs&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;at://steveklabnik.com&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &amp;quot;verificationMethod&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &amp;quot;id&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;did:plc:3danwc67lo7obz2fmdg6jxcr#atproto&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &amp;quot;type&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;Multikey&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &amp;quot;controller&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;did:plc:3danwc67lo7obz2fmdg6jxcr&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &amp;quot;publicKeyMultibase&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;zQ3shfNec2kPEb8cL77gSRMbCwbWE27p9nxKkcc4E82xtW8RJ&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &amp;quot;service&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &amp;quot;id&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;#atproto_pds&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &amp;quot;type&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;AtprotoPersonalDataServer&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &amp;quot;serviceEndpoint&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;https://morel.us-east.host.bsky.network&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This document gives you everything you need to know to determine who I am, that is,
given an arbitrary post that claims it’s written by me, this document describes how
you’d verify that claim.&lt;/p&gt;
&lt;p&gt;We’ll get into how to do that that in a moment, but first, how do you resolve
that DID into that DID document? Well, it’s pretty easy: each method is a
standard that describes how you do that. So when you see &lt;code&gt;did:plc&lt;/code&gt;, that means
we use the PLC standard, which we’ll be going over in a moment. Another method
supported by Bluesky is &lt;code&gt;did:web&lt;/code&gt;. In that case, you wouldn’t use the PLC
standard, you’d use the Web one.&lt;/p&gt;
&lt;p&gt;This is the sense in which DIDs are decentralized: when you present your
identity, you get to decide what method validates that that is a real identity.
There’s no centralized authority that determines which DID types are valid. Now,
of course, that doesn’t mean that every application supports every DID method,
because while this specification is &lt;em&gt;very&lt;/em&gt; generic, you’re still going to have
to write some code to implement that particular method. I could say “Hey I’m
&lt;code&gt;did:foo:1243&lt;/code&gt;” and unless your app supports the &lt;code&gt;foo&lt;/code&gt; method, it’s not gonna
inherently just know what to do. So that is one important caveat.&lt;/p&gt;
&lt;h2 id=&quot;didweb&quot;&gt;&lt;code&gt;did:web&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Let’s explain this resolution process for the &lt;code&gt;web&lt;/code&gt; method. While supported by
Bluesky, a very small number of users actually use &lt;code&gt;did:web&lt;/code&gt;, but it’s a simpler
method and so I think it’s illustrative to go over first. I’ll be using &lt;a href=&quot;https://bsky.app/profile/web.lizthegrey.com&quot;&gt;Liz
Fong-Jones&lt;/a&gt; &lt;code&gt;did:web&lt;/code&gt; account as an
example here. Her identity for that account is &lt;code&gt;did:web:lizthegrey.com&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So how do we resolve this DID into a DID Document? We take the method-specific
identifier, which in this case is &lt;code&gt;lizthegrey.com&lt;/code&gt;, and put it into this URL template:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;https://&amp;lt;id&amp;gt;/.well-known/did.json&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;You can then go fetch this URL to resolve it into the DID Document, which at the
time of writing, looks like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &amp;quot;@context&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &amp;quot;https://www.w3.org/ns/did/v1&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &amp;quot;https://w3id.org/security/multikey/v1&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &amp;quot;https://w3id.org/security/suites/secp256k1-2019/v1&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &amp;quot;id&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;did:web:lizthegrey.com&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &amp;quot;alsoKnownAs&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &amp;quot;at://web.lizthegrey.com&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;    &amp;quot;did:plc:i4tfenpfog244rxry5uz4vtk&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &amp;quot;verificationMethod&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &amp;quot;id&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;did:web:lizthegrey.com#atproto&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &amp;quot;type&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;Multikey&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &amp;quot;controller&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;did:web:lizthegrey.com&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &amp;quot;publicKeyMultibase&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;zQ3shnEqBNR5cuTePW8FyvnrRQaFf6Y7sCi5NBmDpteVXFjb6&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &amp;quot;service&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &amp;quot;id&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;#atproto_pds&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &amp;quot;type&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;AtprotoPersonalDataServer&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;      &amp;quot;serviceEndpoint&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;https://pds.lizthegrey.com&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is very simple! So why might we not want to use &lt;code&gt;did:web&lt;/code&gt;? Why bother with
any other system? Well, this relies on the DNS system. One could make the
argument that ultimately, this is still centralized in some form. If Liz’s
domain registrar were to take away her domain, she would also lose control of
this DID. In a more generic sense, if Liz decides she wants to not use that
domain anymore, she will lose control of that identity to whoever does. That
could be through non-malicious means, like letting it expire and someone else
purchases it, or through malicious ones, like a hack which would compromise her
registrar account and take the domain over.&lt;/p&gt;
&lt;p&gt;Also, you need to have a web server running on that domain with infinite uptime;
if the server goes down, so does your ability to get the document.&lt;/p&gt;
&lt;p&gt;When this DID document changes, there’s no mechanism for clients to know that
it’s changed, which means applications may use one that’s out of date, or that
there is lag between updating the document and updating the application built on
it, which may cause temporary problems until the latest document is fetched.&lt;/p&gt;
&lt;h2 id=&quot;didplc&quot;&gt;&lt;code&gt;did:plc&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;All of these drawbacks led Bluesky to develop their own DID method, which
attempts to fix these problems and others. This method is called
&lt;a href=&quot;https://web.plc.directory/spec/v0.1/did-plc&quot;&gt;&lt;code&gt;did:plc&lt;/code&gt;&lt;/a&gt;. To resolve a &lt;code&gt;did:plc&lt;/code&gt;,
you take the entire DID, and put it in this template:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;https://plc.directory/&amp;lt;did&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;You can then fetch that URL and get the DID document.&lt;/p&gt;
&lt;p&gt;So… what’s the difference? Well, in this case, both nothing and something. In
a very literal sense, both are resolved in the same way: you fetch a URL.
However, the details matter. There is already two ways in which this is different
than DID:Web:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Your DID is no longer tied to a specific domain name. I can let
&lt;code&gt;steveklabnik.com&lt;/code&gt; expire and move to &lt;code&gt;steve.klabnik.com&lt;/code&gt; and my &lt;code&gt;did:plc&lt;/code&gt;
stays the same.&lt;/li&gt;
&lt;li&gt;While a web server still needs to be running, that’s the job of plc.directory, not
my own job. This is operationally much simpler.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I’ve presented the above as pros, but there are also cons. Before, I had to
trust the DNS system and domain registrars, now I have to trust plc.directory.
All of the same caveats apply in that sense, I have to trust that they don’t
take my ID away from me, or that it doesn’t get stolen, etc. However, there are
also some important details that mitigate this, which we’ll get to. But for some
people, neither trusting DNS nor trusting plc.directory is acceptable, and there
are other DID methods that use, for example, a blockchain to resolve the name.
Bluesky does not support using any of those DID methods, so for this
application, it’s not really relevant, but it’s important to know that they
exist.&lt;/p&gt;
&lt;p&gt;Why do it this way? Well, the simplest way to put it is this: setting up a
&lt;code&gt;did:web&lt;/code&gt; involves a lot of “nerd stuff.” You have to register a domain, and
that’s also an ongoing monetary cost. You have to know how to set up a web
server, and author some JSON to put on that server. You have to keep it running.
You have to know how to store your private keys, and keep them safe. It’s a
non-starter compared to “sign up for this web app.” And Bluesky’s goals involves
making this platform accessible to non-nerds. By having plc.directory manage
all of this, we eliminate all of those steps.&lt;/p&gt;
&lt;p&gt;While drafting this post, I have also been made aware of
&lt;a href=&quot;https://identity.foundation/didwebvh/v1.0/&quot;&gt;&lt;code&gt;did:webvh&lt;/code&gt;&lt;/a&gt;, which expands on &lt;code&gt;did:web&lt;/code&gt; and attempts to rectify
some of its shortcomings. I have not read the spec yet, but it has reached 1.0,
so it is probably worth checking out. I wanted to get this post shipped last
week, and didn’t want to delay it further by adding another section, but if
I were writing this post in the future, I’d probably want to talk about it as
well, so just a little heads-up there.&lt;/p&gt;
&lt;h2 id=&quot;does-bluesky-own-your-identity&quot;&gt;Does Bluesky own your identity?&lt;/h2&gt;
&lt;p&gt;But it does also mean that, in some sense, Bluesky still owns your identity.
They’ve generated a keypair for you, and the have access to the secret key.
That’s unacceptable for some people. So how do you fix that?&lt;/p&gt;
&lt;p&gt;Well, &lt;code&gt;did:plc&lt;/code&gt; has some additional features that &lt;code&gt;did:web&lt;/code&gt; does not. For
example, &lt;code&gt;did:plc&lt;/code&gt; will allow you to register additional keypairs with your ID
and use them to rotate your signing keys. This allows you to remove the Bluesky
generated keys and insert your own.&lt;/p&gt;
&lt;p&gt;While that is true, it’s also the case that your PDS needs to use your keys to
sign your posts. As such, most people are likely to store their keys in their PDS,
and so if you are using a Bluesky managed PDS, well, you’ve uploaded your keys to
their infrastructure, and that’s probably not acceptable if you’re trying to keep
your identity away from Bluesky. Of course, the solution there is to run your own
PDS and then rotate your keys. At that point, your key is living on infrastructure
you own, and Bluesky has no say over it any more.&lt;/p&gt;
&lt;p&gt;I think that this possibility is an important design property, and allows
motivated users to meaningfully own their identity. A criticism of this boils
down to “well, most users won’t do that,” and while that’s true, I also think
that’s okay for most people, and that having the choice is more important than
forcing every user to deal with their own key management.&lt;/p&gt;
&lt;h2 id=&quot;in-summary&quot;&gt;In summary&lt;/h2&gt;
&lt;p&gt;This is kind of an abrupt end to this post, but I just wanted to get some things
down ‘on paper’ as it were. I hope you’ve learned a bit about identity and how
it works with atproto.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;Here’s my post about this post on BlueSky:&lt;/p&gt;
&lt;bluesky-post src=&quot;at://did:plc:3danwc67lo7obz2fmdg6jxcr/app.bsky.feed.post/3mqmjx73a2s2w&quot; data-pagefind-ignore=&quot;true&quot;&gt; &lt;div class=&quot;bluesky-embed s-3olstj&quot;&gt;&lt;div class=&quot;highlighted-post s-hik11q&quot;&gt;&lt;div class=&quot;meta s-hik11q&quot;&gt;&lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr&quot; target=&quot;_blank&quot; class=&quot;avatar-wrapper s-hik11q&quot;&gt;&lt;img loading=&quot;lazy&quot; src=&quot;https://cdn.bsky.app/img/avatar/plain/did:plc:3danwc67lo7obz2fmdg6jxcr/bafkreidffwgsdli2xp56t3kfemk7bryow3mygu7zbvgcsxgsu3ntnp4hwm&quot; alt=&quot;&quot; class=&quot;avatar s-hik11q&quot;/&gt;&lt;/a&gt; &lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr&quot; target=&quot;_blank&quot; class=&quot;name-wrapper s-hik11q&quot;&gt;&lt;bdi class=&quot;display-name-wrapper s-hik11q&quot;&gt;&lt;span class=&quot;display-name s-hik11q&quot;&gt;Steve Klabnik&lt;/span&gt;&lt;/bdi&gt; &lt;span class=&quot;handle s-hik11q&quot;&gt;@steveklabnik.com&lt;/span&gt;&lt;/a&gt; &lt;svg class=&quot;logo s-hik11q&quot; fill=&quot;none&quot; viewBox=&quot;0 0 320 286&quot;&gt;&lt;path fill=&quot;#0A7AFF&quot; d=&quot;M69.364 19.146c36.687 27.806 76.147 84.186 90.636 114.439 14.489-30.253 53.948-86.633 90.636-114.439C277.107-.917 320-16.44 320 32.957c0 9.865-5.603 82.875-8.889 94.729-11.423 41.208-53.045 51.719-90.071 45.357 64.719 11.12 81.182 47.953 45.627 84.785-80 82.874-106.667-44.333-106.667-44.333s-26.667 127.207-106.667 44.333c-35.555-36.832-19.092-73.665 45.627-84.785-37.026 6.362-78.648-4.149-90.071-45.357C5.603 115.832 0 42.822 0 32.957 0-16.44 42.893-.917 69.364 19.147Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/div&gt;  &lt;p class=&quot;rich-text is-large s-1lecfnd&quot;&gt;Too many words about DIDs: &lt;a target=&quot;_blank&quot; href=&quot;https://steveklabnik.com/writing/too-many-words-about-dids/&quot; rel=&quot;noopener nofollow&quot; class=&quot;link s-1lecfnd&quot;&gt;steveklabnik.com/writing/too-...&lt;/a&gt;&lt;/p&gt; &lt;div class=&quot;embeds s-azdpbr&quot;&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://steveklabnik.com/writing/too-many-words-about-dids/&quot; rel=&quot;noopener noreferrer nofollow&quot; class=&quot;external-embed s-rtbqd8&quot;&gt; &lt;div class=&quot;meta s-rtbqd8&quot;&gt;&lt;p class=&quot;title s-rtbqd8&quot;&gt;Too many words about DIDs&lt;/p&gt; &lt;p class=&quot;description s-rtbqd8&quot;&gt;Blog post: Too many words about DIDs by Steve Klabnik&lt;/p&gt; &lt;div class=&quot;domain s-rtbqd8&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;2&quot; d=&quot;m4.172 8.07 3.94 2.957.977-1.941 3.887-.978 1.15-4.6M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-6.078 4.865.973-1.946-2.869-1.928-1.89-.12-1.08 1.075 1.947 2.919h2.919Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span class=&quot;domain-name&quot;&gt;steveklabnik.com&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt; &lt;time datetime=&quot;2026-07-14T15:37:00.032Z&quot; class=&quot;date s-hik11q&quot;&gt;July 14, 2026 at 3:37 PM&lt;/time&gt; &lt;div class=&quot;stats s-hik11q&quot;&gt;&lt;span class=&quot;stat s-hik11q&quot; title=&quot;132 likes&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; d=&quot;M12 5.768c6.162-6.25 16.725 5.358 0 14.732C-4.725 11.126 5.838-.482 12 5.768Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span&gt;132&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;stat s-hik11q&quot; title=&quot;29 reposts&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-linecap=&quot;square&quot; stroke-width=&quot;2&quot; d=&quot;m17 3 3 3-3 3M7 21l-3-3 3-3m-2 3h15v-5M4 11V6h15&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span&gt;29&lt;/span&gt;&lt;/span&gt; &lt;div class=&quot;gap s-hik11q&quot;&gt;&lt;/div&gt; &lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr/post/3mqmjx73a2s2w&quot; target=&quot;_blank&quot; class=&quot;permalink s-hik11q&quot;&gt;&lt;span&gt;Read 12 replies on Bluesky&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt; &lt;/bluesky-post&gt;</content:encoded></item><item><title>Thoughts on Bluesky Verification</title><link>https://steveklabnik.com/writing/thoughts-on-bluesky-verification/</link><guid isPermaLink="true">https://steveklabnik.com/writing/thoughts-on-bluesky-verification/</guid><description>Today, Bluesky rolled out blue checks . And, I was given one. Now, I’m not the biggest fan of this sort of feature, however, I also don’t really think this kind of feature is for me. I really like the idea of domain verification; I have been like “oh okay that’s coming from a…</description><pubDate>Mon, 21 Apr 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Today, &lt;a href=&quot;https://bsky.social/about/blog/04-21-2025-verification&quot;&gt;Bluesky rolled out blue checks&lt;/a&gt;. And, I was given one.
Now, I’m not the biggest fan of this sort of feature, however, I also don’t
really think this kind of feature is for me. I really like the idea of domain
verification; I have been like “oh okay that’s coming from a &lt;code&gt;.gov&lt;/code&gt; account”
from time to time. But I don’t think most people really think about domains the
way that programmers do.&lt;/p&gt;
&lt;p&gt;I have wanted to update my &lt;a href=&quot;https://steveklabnik.com/writing/how-does-bluesky-work/&quot;&gt;“How does Bluesky work?”&lt;/a&gt; post for a while
now, but I’ve been super busy. So, let’s ignore the product question for now,
and focus on the technical question. How does verification work?&lt;/p&gt;
&lt;h2 id=&quot;the-golden-rule-of-atproto&quot;&gt;The golden rule of atproto&lt;/h2&gt;
&lt;p&gt;I’ve also been thinking about designing apps on top of atproto. There’s a kind
of rule of thumb that I realized about doing this, a sort of “golden rule” if
you will:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You are the only person who can write records into your PDS.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This has really interesting implications! For example, sometimes people ask for
“soft blocks” on Bluesky. This is a twitter ‘feature’ where if you block
someone, and then unblock them, they’re not following you any more. But on
Bluesky, if you soft block someone, they’re still following you. Why does that
happen?&lt;/p&gt;
&lt;p&gt;Following someone on Bluesky means that you write a record of the lexicon
&lt;a href=&quot;https://github.com/bluesky-social/atproto/blob/a1b2370dbc451570eafb982f326e8c110277ac01/lexicons/app/bsky/graph/follow.json&quot;&gt;&lt;code&gt;app.bsky.graph.follow&lt;/code&gt;&lt;/a&gt; into your PDS. So you might assume that
blocking someone would delete this record from their PDS. But that would violate
the golden rule! You can’t delete records from someone else’s PDS. So, instead,
blocking someone on Bluesky means that you write a record of the lexicon
&lt;a href=&quot;https://github.com/bluesky-social/atproto/blob/a1b2370dbc451570eafb982f326e8c110277ac01/lexicons/app/bsky/graph/block.json&quot;&gt;&lt;code&gt;app.bsky.graph.block&lt;/code&gt;&lt;/a&gt; into your PDS. Unblocking them deletes that
record from your PDS. But it doesn’t delete the record from their PDS. So, if
you block someone, and then unblock them, they still have a record in their PDS
that says they’re following you.&lt;/p&gt;
&lt;p&gt;This may not be the behavior that you want as a user, but it follows from the
constraints of the overall protocol design.&lt;/p&gt;
&lt;h2 id=&quot;how-verification-works&quot;&gt;How verification works&lt;/h2&gt;
&lt;p&gt;Now that we know the golden rule, we can understand how verification works. How
does an account get verified? Well, someone has to be writing a record into a
PDS somewhere. The natural design is the one they’ve chosen: someone becomes
verified by someone else writing a record of the type
&lt;a href=&quot;https://github.com/bluesky-social/atproto/blob/a1b2370dbc451570eafb982f326e8c110277ac01/lexicons/app/bsky/graph/verification.json&quot;&gt;&lt;code&gt;app.bsky.graph.verification&lt;/code&gt;&lt;/a&gt; into their PDS. &lt;a href=&quot;https://pdsls.dev/at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.graph.verification/3lndpy3ngb62l&quot;&gt;Here&lt;/a&gt; is
the record verifying me. It looks like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &amp;quot;$type&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;app.bsky.graph.verification&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &amp;quot;handle&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;steveklabnik.com&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &amp;quot;subject&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;did:plc:3danwc67lo7obz2fmdg6jxcr&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &amp;quot;createdAt&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;2025-04-21T10:49:07.620Z&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt;  &amp;quot;displayName&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&amp;quot;Steve Klabnik&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is in &lt;code&gt;@bsky.app&lt;/code&gt;’s PDS. It describes my DID, and my handle and display
name. One thing not mentioned in the blog post, but is in the comments of the
lexicon, is that changing your handle or display name makes this record invalid.
I didn’t know that! Good to remember in case I decide to make some jokes in my
display name.&lt;/p&gt;
&lt;p&gt;That’s the basics: a record exists, and a blue check shows up on my account. But
wait, isn’t this centralized? I thought Bluesky was decentralized? Well, yes and
no.&lt;/p&gt;
&lt;p&gt;You see, anyone can put a record of this type into their PDS. So, if I wanted to
verify someone else, I can do that too: here’s &lt;a href=&quot;https://pdsls.dev/at://did:plc:3danwc67lo7obz2fmdg6jxcr/app.bsky.graph.verification/3lnduurfk7q2k&quot;&gt;me verifying
&lt;code&gt;@jcsalterego.bsky.social&lt;/code&gt;&lt;/a&gt;. But if you go to Jerry’s profile, you won’t
see a blue check. Why is that? Well, because the Bluesky AppView only shows a
blue check if the record is from a “trusted verifier.” Who is that? Well, as far
as we know, it’s from &lt;code&gt;@bsky.app&lt;/code&gt; and &lt;code&gt;@nytimes.com&lt;/code&gt;. Why can’t we tell more?
Well, they’ve implemented this as a database column in the AppView, it’s not
“in-protocol,” in other words.&lt;/p&gt;
&lt;p&gt;EDIT: Samuel has provided us with the list:&lt;/p&gt;
&lt;bluesky-post src=&quot;at://did:plc:p2cp5gopk7mgjegy6wadk3ep/app.bsky.feed.post/3lndyqyyr4k2k&quot; data-pagefind-ignore=&quot;true&quot;&gt; &lt;div class=&quot;bluesky-embed s-3olstj&quot;&gt;&lt;div class=&quot;highlighted-post s-hik11q&quot;&gt;&lt;div class=&quot;meta s-hik11q&quot;&gt;&lt;a href=&quot;https://bsky.app/profile/did:plc:p2cp5gopk7mgjegy6wadk3ep&quot; target=&quot;_blank&quot; class=&quot;avatar-wrapper s-hik11q&quot;&gt;&lt;img loading=&quot;lazy&quot; src=&quot;https://cdn.bsky.app/img/avatar/plain/did:plc:p2cp5gopk7mgjegy6wadk3ep/bafkreihrdgva6ebn3vmjb4qww3yqozf4eoq26mmraouegpawhr5mo5pnxu&quot; alt=&quot;&quot; class=&quot;avatar s-hik11q&quot;/&gt;&lt;/a&gt; &lt;a href=&quot;https://bsky.app/profile/did:plc:p2cp5gopk7mgjegy6wadk3ep&quot; target=&quot;_blank&quot; class=&quot;name-wrapper s-hik11q&quot;&gt;&lt;bdi class=&quot;display-name-wrapper s-hik11q&quot;&gt;&lt;span class=&quot;display-name s-hik11q&quot;&gt;Samuel&lt;/span&gt;&lt;/bdi&gt; &lt;span class=&quot;handle s-hik11q&quot;&gt;@samuel.fm&lt;/span&gt;&lt;/a&gt; &lt;svg class=&quot;logo s-hik11q&quot; fill=&quot;none&quot; viewBox=&quot;0 0 320 286&quot;&gt;&lt;path fill=&quot;#0A7AFF&quot; d=&quot;M69.364 19.146c36.687 27.806 76.147 84.186 90.636 114.439 14.489-30.253 53.948-86.633 90.636-114.439C277.107-.917 320-16.44 320 32.957c0 9.865-5.603 82.875-8.889 94.729-11.423 41.208-53.045 51.719-90.071 45.357 64.719 11.12 81.182 47.953 45.627 84.785-80 82.874-106.667-44.333-106.667-44.333s-26.667 127.207-106.667 44.333c-35.555-36.832-19.092-73.665 45.627-84.785-37.026 6.362-78.648-4.149-90.071-45.357C5.603 115.832 0 42.822 0 32.957 0-16.44 42.893-.917 69.364 19.147Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/div&gt; &lt;p class=&quot;context s-hik11q&quot;&gt;Replying to an unknown post&lt;/p&gt; &lt;p class=&quot;rich-text is-large s-1lecfnd&quot;&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://bsky.app/profile/did:plc:z72i7hdynmk6r22z27h6tvur&quot; class=&quot;mention s-1lecfnd&quot;&gt;@bsky.app&lt;/a&gt;
&lt;a target=&quot;_blank&quot; href=&quot;https://bsky.app/profile/did:plc:eclio37ymobqex2ncko63h4r&quot; class=&quot;mention s-1lecfnd&quot;&gt;@nytimes.com&lt;/a&gt;
&lt;a target=&quot;_blank&quot; href=&quot;https://bsky.app/profile/did:plc:inz4fkbbp7ms3ixufw6xuvdi&quot; class=&quot;mention s-1lecfnd&quot;&gt;@wired.com&lt;/a&gt; 
&lt;a target=&quot;_blank&quot; href=&quot;https://bsky.app/profile/did:plc:b2kutgxqlltwc6lhs724cfwr&quot; class=&quot;mention s-1lecfnd&quot;&gt;@theathletic.bsky.social&lt;/a&gt;&lt;/p&gt;  &lt;time datetime=&quot;2025-04-21T20:26:13.833Z&quot; class=&quot;date s-hik11q&quot;&gt;April 21, 2025 at 8:26 PM&lt;/time&gt; &lt;div class=&quot;stats s-hik11q&quot;&gt;&lt;span class=&quot;stat s-hik11q&quot; title=&quot;25 likes&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; d=&quot;M12 5.768c6.162-6.25 16.725 5.358 0 14.732C-4.725 11.126 5.838-.482 12 5.768Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span&gt;25&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;stat s-hik11q&quot; title=&quot;10 reposts&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-linecap=&quot;square&quot; stroke-width=&quot;2&quot; d=&quot;m17 3 3 3-3 3M7 21l-3-3 3-3m-2 3h15v-5M4 11V6h15&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span&gt;10&lt;/span&gt;&lt;/span&gt; &lt;div class=&quot;gap s-hik11q&quot;&gt;&lt;/div&gt; &lt;a href=&quot;https://bsky.app/profile/did:plc:p2cp5gopk7mgjegy6wadk3ep/post/3lndyqyyr4k2k&quot; target=&quot;_blank&quot; class=&quot;permalink s-hik11q&quot;&gt;&lt;span&gt;Read 1 reply on Bluesky&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt; &lt;/bluesky-post&gt;
&lt;p&gt;So in some sense this is a centralized feature: clients can display information
however they choose, and they’ve made a product choice that only trusted
verifiers will show up as blue checks. But in another sense, it’s not
centralized, as anyone has the power to verify anyone else. Alternative clients
can decide to show or hide any of this information; &lt;a href=&quot;https://deer.social/&quot;&gt;Deer Social&lt;/a&gt;, one of these
alternate clients, has added a user preference to hide all blue
checks, for example. A different one could show every verification as a blue
check, or display them differently, say one badge per verification, styled like
the avatar of the person who verified you.&lt;/p&gt;
&lt;p&gt;EDIT: turns out that the default AppView also lets you hide blue checks:&lt;/p&gt;
&lt;bluesky-post src=&quot;at://did:plc:35kdk2ntcs626zs6cm62i7ih/app.bsky.feed.post/3lne5sehgxc2y&quot; data-pagefind-ignore=&quot;true&quot;&gt; &lt;div class=&quot;bluesky-embed s-3olstj&quot;&gt;&lt;div class=&quot;post s-12mzi62&quot;&gt;&lt;svg class=&quot;logo s-12mzi62&quot; fill=&quot;none&quot; viewBox=&quot;0 0 320 286&quot;&gt;&lt;path fill=&quot;#0A7AFF&quot; d=&quot;M69.364 19.146c36.687 27.806 76.147 84.186 90.636 114.439 14.489-30.253 53.948-86.633 90.636-114.439C277.107-.917 320-16.44 320 32.957c0 9.865-5.603 82.875-8.889 94.729-11.423 41.208-53.045 51.719-90.071 45.357 64.719 11.12 81.182 47.953 45.627 84.785-80 82.874-106.667-44.333-106.667-44.333s-26.667 127.207-106.667 44.333c-35.555-36.832-19.092-73.665 45.627-84.785-37.026 6.362-78.648-4.149-90.071-45.357C5.603 115.832 0 42.822 0 32.957 0-16.44 42.893-.917 69.364 19.147Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;div class=&quot;aside s-12mzi62&quot;&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr&quot; class=&quot;avatar-wrapper s-12mzi62&quot;&gt;&lt;img loading=&quot;lazy&quot; src=&quot;https://cdn.bsky.app/img/avatar/plain/did:plc:3danwc67lo7obz2fmdg6jxcr/bafkreidffwgsdli2xp56t3kfemk7bryow3mygu7zbvgcsxgsu3ntnp4hwm&quot; alt=&quot;&quot; class=&quot;avatar s-12mzi62&quot;/&gt;&lt;/a&gt; &lt;div class=&quot;line s-12mzi62&quot;&gt;&lt;/div&gt;&lt;/div&gt; &lt;div class=&quot;main s-12mzi62&quot;&gt;&lt;div class=&quot;meta s-12mzi62&quot;&gt;&lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr&quot; target=&quot;_blank&quot; class=&quot;name-wrapper s-12mzi62&quot;&gt;&lt;bdi class=&quot;display-name-wrapper s-12mzi62&quot;&gt;&lt;span class=&quot;display-name s-12mzi62&quot;&gt;Steve Klabnik&lt;/span&gt;&lt;/bdi&gt; &lt;span class=&quot;handle s-12mzi62&quot;&gt;@steveklabnik.com&lt;/span&gt;&lt;/a&gt; &lt;span aria-hidden=&quot;true&quot; class=&quot;dot s-12mzi62&quot;&gt;·&lt;/span&gt; &lt;a target=&quot;_blank&quot; href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr/post/3lne4frl43s2d&quot; title=&quot;April 21, 2025 at 9:31 PM&quot; class=&quot;date s-12mzi62&quot;&gt;&lt;time datetime=&quot;2025-04-21T21:31:31.924Z&quot;&gt;Apr 21, 2025&lt;/time&gt;&lt;/a&gt;&lt;/div&gt;  &lt;p class=&quot;rich-text is-small s-1lecfnd&quot;&gt;Thoughts on Bluesky verification

&lt;a target=&quot;_blank&quot; href=&quot;https://steveklabnik.com/writing/thoughts-on-bluesky-verification/&quot; rel=&quot;noopener nofollow&quot; class=&quot;link s-1lecfnd&quot;&gt;steveklabnik.com/writing/thou...&lt;/a&gt;&lt;/p&gt; &lt;div class=&quot;embeds s-azdpbr&quot;&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://steveklabnik.com/writing/thoughts-on-bluesky-verification/&quot; rel=&quot;noopener noreferrer nofollow&quot; class=&quot;external-embed s-rtbqd8&quot;&gt; &lt;div class=&quot;meta s-rtbqd8&quot;&gt;&lt;p class=&quot;title s-rtbqd8&quot;&gt;Thoughts on Bluesky Verification&lt;/p&gt; &lt;p class=&quot;description s-rtbqd8&quot;&gt;&lt;/p&gt; &lt;div class=&quot;domain s-rtbqd8&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;2&quot; d=&quot;m4.172 8.07 3.94 2.957.977-1.941 3.887-.978 1.15-4.6M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-6.078 4.865.973-1.946-2.869-1.928-1.89-.12-1.08 1.075 1.947 2.919h2.919Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span class=&quot;domain-name&quot;&gt;steveklabnik.com&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;highlighted-post s-hik11q&quot;&gt;&lt;div class=&quot;meta s-hik11q&quot;&gt;&lt;a href=&quot;https://bsky.app/profile/did:plc:35kdk2ntcs626zs6cm62i7ih&quot; target=&quot;_blank&quot; class=&quot;avatar-wrapper s-hik11q&quot;&gt;&lt;img loading=&quot;lazy&quot; src=&quot;https://cdn.bsky.app/img/avatar/plain/did:plc:35kdk2ntcs626zs6cm62i7ih/bafkreieezekf5jp4apfb6y3kfam5tvs32ktqbgtoq5waqunu2omo7tufkq&quot; alt=&quot;&quot; class=&quot;avatar s-hik11q&quot;/&gt;&lt;/a&gt; &lt;a href=&quot;https://bsky.app/profile/did:plc:35kdk2ntcs626zs6cm62i7ih&quot; target=&quot;_blank&quot; class=&quot;name-wrapper s-hik11q&quot;&gt;&lt;bdi class=&quot;display-name-wrapper s-hik11q&quot;&gt;&lt;span class=&quot;display-name s-hik11q&quot;&gt;jolheiser&lt;/span&gt;&lt;/bdi&gt; &lt;span class=&quot;handle s-hik11q&quot;&gt;@jolheiser.com&lt;/span&gt;&lt;/a&gt; &lt;/div&gt;  &lt;p class=&quot;rich-text is-large s-1lecfnd&quot;&gt;This was very informative, thanks for the write-up! 
I was curious about being able to hide the checkmarks, but unless I&apos;m mistaken this appears to also be an option on the bluesky appview. 
At least I was able to check the preference in my settings-&gt;moderation-&gt;verification settings&lt;/p&gt;  &lt;time datetime=&quot;2025-04-21T21:56:28.122Z&quot; class=&quot;date s-hik11q&quot;&gt;April 21, 2025 at 9:56 PM&lt;/time&gt; &lt;div class=&quot;stats s-hik11q&quot;&gt;&lt;span class=&quot;stat s-hik11q&quot; title=&quot;2 likes&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; d=&quot;M12 5.768c6.162-6.25 16.725 5.358 0 14.732C-4.725 11.126 5.838-.482 12 5.768Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span&gt;2&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;stat s-hik11q&quot; title=&quot;0 reposts&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-linecap=&quot;square&quot; stroke-width=&quot;2&quot; d=&quot;m17 3 3 3-3 3M7 21l-3-3 3-3m-2 3h15v-5M4 11V6h15&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span&gt;0&lt;/span&gt;&lt;/span&gt; &lt;div class=&quot;gap s-hik11q&quot;&gt;&lt;/div&gt; &lt;a href=&quot;https://bsky.app/profile/did:plc:35kdk2ntcs626zs6cm62i7ih/post/3lne5sehgxc2y&quot; target=&quot;_blank&quot; class=&quot;permalink s-hik11q&quot;&gt;&lt;span&gt;Read 1 reply on Bluesky&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt; &lt;/bluesky-post&gt;
&lt;p&gt;The point is still the same though: there’s choice here. Back to the original post!&lt;/p&gt;
&lt;p&gt;The underlying protocol is totally open, but you can make an argument that most
users will use the main client, and therefore, in practice it’s more centralized
than not. My mental model of it is the bundled list of root CAs that browsers
ship; in theory, DNS is completely decentralized, but in practice, a few root
CAs are more trusted than others. It’s sort of similar here, except there’s no
real “delegation” involved: verifiers are peers, not a tree.&lt;/p&gt;
&lt;p&gt;This core design allows Bluesky to adjust the way it works in the future fairly
easily, they could allow you to decide who to trust, for example. We’ll see how
this feature evolves over time.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;I’m flattered that I was chosen to be verified; if I was trying to ship this
feature, my name wouldn’t come up 181st on the list. I was really curious about
the design when they announced this feature, I assumed it was going to be closer
to a PGP web of trust, or delegated in some way. This design is much simpler and
less centralized than I expected: this is arguably more horizontal than the web
of trust would have been.&lt;/p&gt;
&lt;p&gt;At the same time, I am interested in seeing if this changes the culture of the
site; some see the blue check as a status symbol of some kind, and think it
means what you say matters more. I don’t think that’s true, personally, but it
doesn’t really matter what I think. To redraw the analogy with DNS, the blue
check is very similar to the green lock: it doesn’t mean that what you’re saying
is true, or right, or good, it just means that you are who you say you are. But
even though a blue check is technically isomorphic (or close enough) to a green
lock, I think a lot of people perceive it as being more than that. We’ll just
have to see. What I am glad about it is that it’s an in-protocol design, rather
than an external one like DMs are. I understand why they did it that way, but
I’d rather that remain the exception rather than the rule.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;Here’s my post about this post on BlueSky:&lt;/p&gt;
&lt;bluesky-post src=&quot;at://did:plc:3danwc67lo7obz2fmdg6jxcr/app.bsky.feed.post/3lne4frl43s2d&quot; data-pagefind-ignore=&quot;true&quot;&gt; &lt;div class=&quot;bluesky-embed s-3olstj&quot;&gt;&lt;div class=&quot;highlighted-post s-hik11q&quot;&gt;&lt;div class=&quot;meta s-hik11q&quot;&gt;&lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr&quot; target=&quot;_blank&quot; class=&quot;avatar-wrapper s-hik11q&quot;&gt;&lt;img loading=&quot;lazy&quot; src=&quot;https://cdn.bsky.app/img/avatar/plain/did:plc:3danwc67lo7obz2fmdg6jxcr/bafkreidffwgsdli2xp56t3kfemk7bryow3mygu7zbvgcsxgsu3ntnp4hwm&quot; alt=&quot;&quot; class=&quot;avatar s-hik11q&quot;/&gt;&lt;/a&gt; &lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr&quot; target=&quot;_blank&quot; class=&quot;name-wrapper s-hik11q&quot;&gt;&lt;bdi class=&quot;display-name-wrapper s-hik11q&quot;&gt;&lt;span class=&quot;display-name s-hik11q&quot;&gt;Steve Klabnik&lt;/span&gt;&lt;/bdi&gt; &lt;span class=&quot;handle s-hik11q&quot;&gt;@steveklabnik.com&lt;/span&gt;&lt;/a&gt; &lt;svg class=&quot;logo s-hik11q&quot; fill=&quot;none&quot; viewBox=&quot;0 0 320 286&quot;&gt;&lt;path fill=&quot;#0A7AFF&quot; d=&quot;M69.364 19.146c36.687 27.806 76.147 84.186 90.636 114.439 14.489-30.253 53.948-86.633 90.636-114.439C277.107-.917 320-16.44 320 32.957c0 9.865-5.603 82.875-8.889 94.729-11.423 41.208-53.045 51.719-90.071 45.357 64.719 11.12 81.182 47.953 45.627 84.785-80 82.874-106.667-44.333-106.667-44.333s-26.667 127.207-106.667 44.333c-35.555-36.832-19.092-73.665 45.627-84.785-37.026 6.362-78.648-4.149-90.071-45.357C5.603 115.832 0 42.822 0 32.957 0-16.44 42.893-.917 69.364 19.147Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/div&gt;  &lt;p class=&quot;rich-text is-large s-1lecfnd&quot;&gt;Thoughts on Bluesky verification

&lt;a target=&quot;_blank&quot; href=&quot;https://steveklabnik.com/writing/thoughts-on-bluesky-verification/&quot; rel=&quot;noopener nofollow&quot; class=&quot;link s-1lecfnd&quot;&gt;steveklabnik.com/writing/thou...&lt;/a&gt;&lt;/p&gt; &lt;div class=&quot;embeds s-azdpbr&quot;&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://steveklabnik.com/writing/thoughts-on-bluesky-verification/&quot; rel=&quot;noopener noreferrer nofollow&quot; class=&quot;external-embed s-rtbqd8&quot;&gt; &lt;div class=&quot;meta s-rtbqd8&quot;&gt;&lt;p class=&quot;title s-rtbqd8&quot;&gt;Thoughts on Bluesky Verification&lt;/p&gt; &lt;p class=&quot;description s-rtbqd8&quot;&gt;&lt;/p&gt; &lt;div class=&quot;domain s-rtbqd8&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;2&quot; d=&quot;m4.172 8.07 3.94 2.957.977-1.941 3.887-.978 1.15-4.6M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-6.078 4.865.973-1.946-2.869-1.928-1.89-.12-1.08 1.075 1.947 2.919h2.919Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span class=&quot;domain-name&quot;&gt;steveklabnik.com&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/a&gt;&lt;/div&gt; &lt;time datetime=&quot;2025-04-21T21:31:31.924Z&quot; class=&quot;date s-hik11q&quot;&gt;April 21, 2025 at 9:31 PM&lt;/time&gt; &lt;div class=&quot;stats s-hik11q&quot;&gt;&lt;span class=&quot;stat s-hik11q&quot; title=&quot;227 likes&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; d=&quot;M12 5.768c6.162-6.25 16.725 5.358 0 14.732C-4.725 11.126 5.838-.482 12 5.768Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span&gt;227&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;stat s-hik11q&quot; title=&quot;48 reposts&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-linecap=&quot;square&quot; stroke-width=&quot;2&quot; d=&quot;m17 3 3 3-3 3M7 21l-3-3 3-3m-2 3h15v-5M4 11V6h15&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span&gt;48&lt;/span&gt;&lt;/span&gt; &lt;div class=&quot;gap s-hik11q&quot;&gt;&lt;/div&gt; &lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr/post/3lne4frl43s2d&quot; target=&quot;_blank&quot; class=&quot;permalink s-hik11q&quot;&gt;&lt;span&gt;Read 24 replies on Bluesky&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt; &lt;/bluesky-post&gt;</content:encoded></item><item><title>How Does BlueSky Work?</title><link>https://steveklabnik.com/writing/how-does-bluesky-work/</link><guid isPermaLink="true">https://steveklabnik.com/writing/how-does-bluesky-work/</guid><description>One of the reasons I am enthusiastic about BlueSky is because of the way that it works. So in this post, I am going to lay out some of the design and the principles behind this design, as I understand them. I am not on the BlueSky team, so these are my takes only. Let’s begin.…</description><pubDate>Sat, 24 Feb 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;One of the reasons I am enthusiastic about BlueSky is because of the way that
it works. So in this post, I am going to lay out some of the design and the
principles behind this design, as I understand them. I am not on the BlueSky
team, so these are my takes only.&lt;/p&gt;
&lt;p&gt;Let’s begin.&lt;/p&gt;
&lt;h2 id=&quot;why-does-bluesky-exist&quot;&gt;Why does BlueSky exist?&lt;/h2&gt;
&lt;p&gt;Here’s what &lt;a href=&quot;https://bsky.social&quot;&gt;the BlueSky Website&lt;/a&gt; says right now:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Social media is too important to be controlled by a few corporations. We’re
building an open foundation for the social internet so that we can all shape
its future.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is the big picture.&lt;/p&gt;
&lt;p&gt;Okay so that’s a great idea, but like, what does that &lt;em&gt;mean&lt;/em&gt;? Currently,
BlueSky is a microblogging application, similar to Twitter and Mastodon. How
does that fit into the big picture? Well, while it’s true that BlueSky is a
microblogging application, that’s not the whole story: BlueSky is an initial
application to prove out the viability of &lt;a href=&quot;https://atproto.com/&quot;&gt;the Authenicated Transfer
Protocol&lt;/a&gt;, known as AT, ATP, or “atproto” for short. BlueSky is the
“building” and atproto is the “open foundation for the social internet.”&lt;/p&gt;
&lt;p&gt;An important thing to note: BlueSky is also a company. Some people look at a
company saying “hey we’re building something that’s too big to be controlled
by companies!” with skepticism. I think that’s a healthy starting point, but
the answer for me is atproto.&lt;/p&gt;
&lt;p&gt;The interplay between these two things is important, but we’re going to start
by exploring atproto, and then talk about how BlueSky is built on top of it.&lt;/p&gt;
&lt;h2 id=&quot;is-this-a-cryptocurrency&quot;&gt;Is this a cryptocurrency?&lt;/h2&gt;
&lt;p&gt;The first thing we have to get out of the way: If you hear “oh it’s a
distributed network called ‘something protocol’” you may have a “is this
a cryptocurrency?” alarm bell going off in your head.&lt;/p&gt;
&lt;p&gt;Don’t worry, it’s not a cryptocurrency. It does use some technologies that
originated in the cryptocurrency space, but this isn’t a blockchain, or a DAO,
or NFTs, or any of that. Just some cryptography and merkle trees and the like.&lt;/p&gt;
&lt;h2 id=&quot;what-is-the-big-picture-with-atproto&quot;&gt;What is the big picture with atproto?&lt;/h2&gt;
&lt;p&gt;Here’s what &lt;a href=&quot;https://atproto.com/guides/overview&quot;&gt;the AT Protocol Overview&lt;/a&gt; says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The Authenticated Transfer Protocol, aka atproto, is a federated protocol for
large-scale distributed social applications.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Let’s break that down:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;a federated protocol&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;atproto is federated. This means that the various parts of the system can have
multiple people running them, and that they communicate with each other.&lt;/p&gt;
&lt;p&gt;Choosing federation is a big part of how atproto delivers on the “can’t be
controlled by one organization” promise. There are other parts too, but this
is an important aspect of solving this.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;for large-scale&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If you want to scale, you have to design with scale in mind. atproto makes
several interesting choices in order to distribute the load of running the
system more onto the actors that can handle load, and less on those that can’t.
This way, applications running on top of atproto can scale up to large userbases
without issue.&lt;/p&gt;
&lt;p&gt;That’s the hope, at least. Earlier this week, BlueSky hit five million users,
and is far more stable than Twitter was in the early days. That’s not as big
as many social applications, but it’s not nothing either. We’ll see how this
works out in practice.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;distributed social applications&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;atproto is for connecting to others, so it’s focused on social applications.
It also is currently 100% public, there are no private messages or similar. The
reasons for this is that achieving private things in a federated system is
very tricky, and they would rather get it right than ship something with serious
caveats. Best for now to only use this stuff for things you want to be public.&lt;/p&gt;
&lt;p&gt;These applications are “distributed” because running them involves running them
on the network directly. There’s no “BlueSky server,” there’s just servers
running atproto distributing messages to each other, both BlueSky messages and
whatever other messages from whatever other applications people create.&lt;/p&gt;
&lt;p&gt;So that’s the high level, but what does that mean concretely?&lt;/p&gt;
&lt;p&gt;In atproto, &lt;em&gt;users&lt;/em&gt; create &lt;em&gt;records&lt;/em&gt; that are cryptographically signed to
demonstrate authorship. Records have a schema called a &lt;em&gt;Lexicon&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Records are stored in &lt;em&gt;repositories&lt;/em&gt;. Repositories run as a &lt;em&gt;service&lt;/em&gt;, exposing
HTTP and WebSockets. They then can then talk to each other and federate the
records. These are often called PDSes, for “Personal Data Server.” Users
either run their own PDS, or use one that someone else hosts for them.&lt;/p&gt;
&lt;p&gt;Applications can be built by looking at the various records stored in the
network, and doing things with them. These services all called &lt;em&gt;App Views&lt;/em&gt;,
because they are exposing a particular view of the information stored in the
network. This view is created via the Lexicon system: building an application
means that you define a Lexicon, structuring the data that you want to deal with,
and then look at records that use your lexicon, ignoring the rest.&lt;/p&gt;
&lt;p&gt;Now, if this were all there is, there would be pretty serious scaling issues.
For example, if every time I post a new update on BlueSky, if I had to send
my post to every single one of my followers’ repositories, that would be
extremely inefficent, and make running a popular repository very expensive to
run. To fix this, there’s an additional kind of service, called a &lt;em&gt;relay&lt;/em&gt;, that
aggregates information in the network, and exposes it as a firehose to others.
So in practice, App Views don’t look at Repositories, but instead, look at
Relays. When I make a post, my respository won’t notify my followers’
repositories individually. My repository will notify a Relay, and my followers
will use an App View that filters the ouput of the Relay to show only the posts
of people they’re following. This does imply that Relays are often huge and
expensive to run, however you could imagine running a smaller relay that only
propogates posts from a smaller subset of users too. They don’t &lt;em&gt;have&lt;/em&gt; to show
everything on the network, though bigger ones will, of course.&lt;/p&gt;
&lt;p&gt;Here this is in ASCII art:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ┌─────┐                    ┌──────────┐&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  │ PDS ├───────┐            │ App View │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  └─────┘       │            └──────────┘&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;               ┌▼────────┐       ▲&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ┌─────┐      │         ├───────┘&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  │ PDS ├──────►  Relay  │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  └─────┘      │         ├───────┐&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;               └▲────────┘       ▼&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  ┌─────┐       │            ┌──────────┐&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  │ PDS ├───────┘            │ App View │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  └─────┘                    └──────────┘&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is all you really need to know to understand the core of atproto: people
create data, it’s shared in the network, and applications can interact with
that data.&lt;/p&gt;
&lt;p&gt;However, there are additional service types being introduced, with the
possibility of more in the future. But before we talk about those, we have to
explain some ideological commitments to understand why things are shaped the way
they are.&lt;/p&gt;
&lt;h2 id=&quot;what-is-speech-vs-reach&quot;&gt;What is “speech vs reach”?&lt;/h2&gt;
&lt;p&gt;Given that atproto is deliberately created to enable social applications, it
needs to consider not just connecting people, but also disconnecting people.
Moderation is a core component of any social application: “no moderation” is
still a moderation strategy. BlueSky handles these sorts of questions by
acknowledging that different people will have different preferences when it
comes to moderation, and also that moderation at scale is difficult.&lt;/p&gt;
&lt;p&gt;As such, the protocol takes a “speech vs reach” approach to moderation. The
stuff we’ve described so far falls under the “speech” layer. It is purely
concerned with replicating your content across the network, without caring
what the semantic contents of that content is. Moderation tools fall under the
“reach” layer: you take all of that speech, but provide a way to limit the
reach of stuff you don’t care to see yourself.&lt;/p&gt;
&lt;p&gt;Sometimes, people say that BlueSky is “all about free speech” or “doesn’t do
moderation.” This is simply inaccurate. Moderation tooling is encoded into the
protocol itself, so that it can work with all content on the network, even
non-BlueSky applications. Moreover, it gives you the ability to choose your own
moderators, so that you aren’t beholden to anyone else’s choice of moderation or
lack thereof. But I’m getting ahead of myself: let’s talk about feed generators
and labelers.&lt;/p&gt;
&lt;h2 id=&quot;what-are-feed-generators&quot;&gt;What are feed generators?&lt;/h2&gt;
&lt;p&gt;Most social applications have the concept of a “feed” of content. This is broken
out into its own kind of service in atproto, called a &lt;em&gt;feed generator&lt;/em&gt;. A classic
example of a feed is “computer, show me the posts of the people I follow in
reverse chronological order.” Lately, algorithmic feeds have become popular with
social networks, to the point of where some non-technical users refer to them
as “algorithms.”&lt;/p&gt;
&lt;p&gt;Feed generators take the firehose produced by a relay, and then show you a list
of content, filtered and ordered by whatever metric the feed generator desires.
You can then share these feeds with other users.&lt;/p&gt;
&lt;p&gt;As a practical example, one of my favorite feeds is the &lt;a href=&quot;https://bsky.app/profile/did:plc:vpkhqolt662uhesyj6nxm7ys/feed/infreq&quot;&gt;Quiet
Posters&lt;/a&gt; feed. This feed shows posts by people who don’t post
very often. This makes it so much easier to keep up with people who get drowned
out of my main feed. There are feeds like &lt;a href=&quot;https://bsky.app/profile/did:plc:vpkhqolt662uhesyj6nxm7ys/feed/followpics&quot;&gt;the ‘Gram&lt;/a&gt;, which shows
only posts that have pictures attatched. Or &lt;a href=&quot;https://bsky.app/profile/did:plc:q6gjnaw2blty4crticxkmujt/feed/bangers&quot;&gt;My Bangers&lt;/a&gt;, which shows
your most popular posts.&lt;/p&gt;
&lt;p&gt;This to me is one of the killer features of BlueSky over other microblogging
tools: total user choice. If I want to make my own algorithm, I can do so.
And I can share them easily with others. If you use BlueSky, you can visit
any of those feeds and follow them too.&lt;/p&gt;
&lt;p&gt;Feeds are a recent addition to atproto, and therefore, while they do exist,
they may not be feature complete just yet, and may undergo some change in the
future. We’ll see. They’re working just fine from my perspective, but I haven’t
been following the lower level technical details.&lt;/p&gt;
&lt;h2 id=&quot;what-are-labelers&quot;&gt;What are labelers?&lt;/h2&gt;
&lt;p&gt;A &lt;em&gt;Labeler&lt;/em&gt; is a service that applies &lt;em&gt;labels&lt;/em&gt; to content or accounts. As a user,
you can subscribe to a particular labeler, and then have your experience change
based on the labels on posts.&lt;/p&gt;
&lt;p&gt;A labeler can do this via whatever method it pleases: automatically by running
some sort of algorithm on posts, manually by having some human give a thumbs
up or thumbs down, whatever method the person running the labeling service
wants.&lt;/p&gt;
&lt;p&gt;An example of a labeling service would be a blocklist: a label on the posts
authored by people whose content you don’t want to see. Another example is
an NSFW filter, which may run some sort of algorithm over pictures in posts,
and labeling them if they believe they contain NSFW content.&lt;/p&gt;
&lt;p&gt;Labeling exists, but I do not believe you can run your own labeler yet. BlueSky
runs their own, but there hasn’t been an external release that I am aware of.
But once they do, you can imagine communities running their own services, adding
whatever kind of labels they’d like.&lt;/p&gt;
&lt;h2 id=&quot;how-does-moderation-work-in-atproto&quot;&gt;How does moderation work in atproto?&lt;/h2&gt;
&lt;p&gt;Putting this all together, we can see how moderation works: Feeds may choose to
transform the feed based on labels, or App Views may take feeds and apply
transformations based on asking a Labeler about it. These can
be mixed and matched based on preference.&lt;/p&gt;
&lt;p&gt;This means you can choose your moderation experience, not just in applications,
but also within it. Want a SFW feed, but allow NSFW content in another? You
can do that. Want to produce a blocklist of people and share it with the
world? You can do that.&lt;/p&gt;
&lt;p&gt;Because these moderation tools work at the network level, rather than at the
application level, they actually go &lt;em&gt;further&lt;/em&gt; than in other systems. If someone
builds an Instagram clone on atproto, that could also use your blocklist
labeller, since your blocklist labeller works at the protocol level. Block
someone in one place, and they can be blocked on every place, if you so choose.
Maybe you subscribe to different moderation decisions in different applications.
It is 100% up to you.&lt;/p&gt;
&lt;p&gt;This model is significantly different from other federated systems, because
you don’t really have an “account” on an “instance,” like in Mastodon. So a lot
of people ask questions like “what happens when my instance gets defederated”
which don’t exactly make sense as stated. You can achieve the same goal, by
blocking a set of users based on some criteria, maybe you dislike a certain
PDS and want to ignore posts that come from a certain one, but that is &lt;em&gt;your&lt;/em&gt;
choice and yours alone, it is not dictated by some “server owner” that your
account resides on.&lt;/p&gt;
&lt;p&gt;So if you don’t have a home server, how does identity work?&lt;/p&gt;
&lt;h2 id=&quot;how-does-identity-and-account-portability-work&quot;&gt;How does identity and account portability work?&lt;/h2&gt;
&lt;p&gt;There are a LOT of details to how identity works, so I’m going to focus on the
parts that I find important. I am also going to focus on the part that is
controversial, because that is important to talk about.&lt;/p&gt;
&lt;p&gt;At its core, users have an identity number, called a “Decentralized Identifier,”
or &lt;em&gt;&lt;a href=&quot;https://www.w3.org/TR/did-core/&quot;&gt;DID&lt;/a&gt;&lt;/em&gt;. My DID looks like this: &lt;code&gt;did:plc:3danwc67lo7obz2fmdg6jxcr&lt;/code&gt;.
Feel free to follow me! Lol, of course that’s not the interface that you’ll see
most of the time. Identity also involves a &lt;em&gt;handle&lt;/em&gt;, which is a domain name.
My handle is &lt;code&gt;steveklabnik.com&lt;/code&gt;, unsurprisingly. You’ll see my posts on BlueSky
as coming from &lt;code&gt;@steveklabnik.com&lt;/code&gt;. This system also works well for people who
don’t own a domain; if you sign up for BlueSky, it’ll give you the ability to
choose a name, and then your handle is &lt;code&gt;@username.bsky.social&lt;/code&gt;. I started off
making posts as &lt;code&gt;@steveklabnik.bsky.social&lt;/code&gt;, and then moved to
&lt;code&gt;@steveklabnik.com&lt;/code&gt;. But because the DID is stable, there was no disruption to
my followers. They just saw the handle update in the UI.&lt;/p&gt;
&lt;p&gt;You can use a domain as your handle by getting the DID your PDS generated for
you, and then adding a &lt;code&gt;TXT&lt;/code&gt; record in the DNS you use for that domain. If
you’re not the kind of person who uses or even knows what DNS is, I envy you,
but you can also use BlueSky’s partnership with NameCheap to register a domain
and configure it to use as a handle without any technical knowledge necessary.
You can then log into applications with your domain as the handle, and
everything works nicely.&lt;/p&gt;
&lt;p&gt;This is also how BlueSky delivers true “account portability,” partially because,
well, there isn’t really a concept of an account. The person who uses a given
DID uses cryptography to sign the content they create, and then that content
is replicated across the network. “Your account” can’t really be terminated,
because that would mean someone forcibly stopping you from using keys that they
don’t even have access to. If your PDS goes down, and you want to migrate to
a new one, there’s a way to backfill the contents of the PDS from the network
itself, and inform the network that your PDS has moved. It is real, meaningful
account portability, and that is radically different from any similar service
running today.&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;But.&lt;/p&gt;
&lt;p&gt;The devil is in the details, and I think this is one of the more meaningful
criticisms of BlueSky and atproto.&lt;/p&gt;
&lt;p&gt;You see, there are different “methods” of creating a DID. BlueSky supports
two methods: &lt;code&gt;did:web&lt;/code&gt;, which is based on domain names. There are some drawbacks
with this method that I don’t personally fully understand well enough to describe,
I’m sure I’ll write something in-depth about DIDs in the future.&lt;/p&gt;
&lt;p&gt;So because of that weakness, BlueSky has implemented their own DID method,
called &lt;code&gt;did:plc&lt;/code&gt;. The &lt;code&gt;plc&lt;/code&gt; stands for “placeholder,” because even though
they plan on supporting it indefinitely, it too has its weaknesses. And that
weakness is that it involves asking a service that BlueSky runs in order to
resolve the proper information. For example, &lt;a href=&quot;https://plc.directory/did:plc:3danwc67lo7obz2fmdg6jxcr&quot;&gt;here is my lookup&lt;/a&gt;.
This means that BlueSky can ban you in a more serious way than is otherwise
possible thanks to the network design, which some people take to be a very
serious issue.&lt;/p&gt;
&lt;p&gt;So, is the flaw fatal? I don’t think so. The first reason is, if you really don’t
want to engage with it, you can use &lt;code&gt;did:web&lt;/code&gt;. Yes that isn’t great for other
reasons; that’s why &lt;code&gt;did:plc&lt;/code&gt; was created. But you do get around this issue.&lt;/p&gt;
&lt;p&gt;Another is that the BlueSky team has demonstrated, in my personal opinion,
enough understanding and uncomfortableness with being in control here, and it’s
designed in such a way that if other, better systems develop, you can move
to them. They’ve also indicated that moving governance of &lt;code&gt;did:plc&lt;/code&gt; to some sort
of consensus model in the future is possible. There are options. Also, others
could run a &lt;code&gt;did:plc&lt;/code&gt; service and use that instead if they prefer, too.&lt;/p&gt;
&lt;p&gt;I personally see this as an example of pragmatically shipping something, others
see it as a nefarious plot. You’ll have to decide for yourself.&lt;/p&gt;
&lt;h2 id=&quot;how-is-bluesky-built-on-top-of-atproto&quot;&gt;How is BlueSky built on top of atproto?&lt;/h2&gt;
&lt;p&gt;So, now that we understand atproto, we can understand BlueSky. BlueSky is
an application built on top of the atproto network. They run an App View, and
&lt;a href=&quot;https://bsky.app/&quot;&gt;a web application&lt;/a&gt; that uses that App View to work. They also run a PDS
for users that sign up through the web app, as well as a relay that those PDSes
communicate with.&lt;/p&gt;
&lt;p&gt;They publish two Lexicons, one as &lt;code&gt;com.atproto.*&lt;/code&gt; and one as &lt;code&gt;app.bsky.*&lt;/code&gt;. The
former are low level operations that any application on the network will need,
and the ones specific to BlueSky are in the latter.&lt;/p&gt;
&lt;p&gt;But one nice thing about BlueSky in particular is that they’ve taken the product
goals that nobody should know any of this nerd shit to be able to use BlueSky.
The lack of instances means there’s no “I need to pick an instance to create an
account” flow, and the portability means that if my host goes down, I can move,
and my followers are none the wiser.&lt;/p&gt;
&lt;h2 id=&quot;how-will-others-build-applications-on-top-of-atproto&quot;&gt;How will others build applications on top of atproto?&lt;/h2&gt;
&lt;p&gt;You can create an atproto app by creating a Lexicon. You’ll then want to run
an App View that does things with data on the network involving your lexicon,
and your application will want to give people the ability to write data to their
PDS using your lexicon.&lt;/p&gt;
&lt;p&gt;I myself am considering doing so. We’ll see.&lt;/p&gt;
&lt;h2 id=&quot;concluding-thoughts&quot;&gt;Concluding thoughts&lt;/h2&gt;
&lt;p&gt;So yeah, on the technical side of things, that’s an overview of how atproto and
BlueSky work. I think this design is very clever. Furthermore, I think the
separation of concerns between atproto and BlueSky are very meaningful, as having
a “killer app” for the network gives a reason to use it. It also is a form of
dogfooding, making sure that atproto is good enough to be able to build real
applications on.&lt;/p&gt;
&lt;p&gt;I’m sure I’ll have more to say about all of this in the future.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;Here’s my post about this post on BlueSky:&lt;/p&gt;
&lt;bluesky-post src=&quot;at://did:plc:3danwc67lo7obz2fmdg6jxcr/app.bsky.feed.post/3km6y2x6cxk2f&quot; data-pagefind-ignore=&quot;true&quot;&gt; &lt;div class=&quot;bluesky-embed s-3olstj&quot;&gt;&lt;div class=&quot;highlighted-post s-hik11q&quot;&gt;&lt;div class=&quot;meta s-hik11q&quot;&gt;&lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr&quot; target=&quot;_blank&quot; class=&quot;avatar-wrapper s-hik11q&quot;&gt;&lt;img loading=&quot;lazy&quot; src=&quot;https://cdn.bsky.app/img/avatar/plain/did:plc:3danwc67lo7obz2fmdg6jxcr/bafkreidffwgsdli2xp56t3kfemk7bryow3mygu7zbvgcsxgsu3ntnp4hwm&quot; alt=&quot;&quot; class=&quot;avatar s-hik11q&quot;/&gt;&lt;/a&gt; &lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr&quot; target=&quot;_blank&quot; class=&quot;name-wrapper s-hik11q&quot;&gt;&lt;bdi class=&quot;display-name-wrapper s-hik11q&quot;&gt;&lt;span class=&quot;display-name s-hik11q&quot;&gt;Steve Klabnik&lt;/span&gt;&lt;/bdi&gt; &lt;span class=&quot;handle s-hik11q&quot;&gt;@steveklabnik.com&lt;/span&gt;&lt;/a&gt; &lt;svg class=&quot;logo s-hik11q&quot; fill=&quot;none&quot; viewBox=&quot;0 0 320 286&quot;&gt;&lt;path fill=&quot;#0A7AFF&quot; d=&quot;M69.364 19.146c36.687 27.806 76.147 84.186 90.636 114.439 14.489-30.253 53.948-86.633 90.636-114.439C277.107-.917 320-16.44 320 32.957c0 9.865-5.603 82.875-8.889 94.729-11.423 41.208-53.045 51.719-90.071 45.357 64.719 11.12 81.182 47.953 45.627 84.785-80 82.874-106.667-44.333-106.667-44.333s-26.667 127.207-106.667 44.333c-35.555-36.832-19.092-73.665 45.627-84.785-37.026 6.362-78.648-4.149-90.071-45.357C5.603 115.832 0 42.822 0 32.957 0-16.44 42.893-.917 69.364 19.147Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/div&gt;  &lt;p class=&quot;rich-text is-large s-1lecfnd&quot;&gt;With BlueSky finally opening up federation, I think it&apos;s time to write up something that explains the whole thing, BlueSky, atproto, the works, in one easy to find place. Just the high level bits, hopefully something that any developer can understand: &lt;a target=&quot;_blank&quot; href=&quot;https://steveklabnik.com/writing/how-does-bluesky-work&quot; rel=&quot;noopener nofollow&quot; class=&quot;link s-1lecfnd&quot;&gt;steveklabnik.com/writing/how-...&lt;/a&gt;&lt;/p&gt;  &lt;time datetime=&quot;2024-02-24T21:39:11.227Z&quot; class=&quot;date s-hik11q&quot;&gt;February 24, 2024 at 9:39 PM&lt;/time&gt; &lt;div class=&quot;stats s-hik11q&quot;&gt;&lt;span class=&quot;stat s-hik11q&quot; title=&quot;665 likes&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; d=&quot;M12 5.768c6.162-6.25 16.725 5.358 0 14.732C-4.725 11.126 5.838-.482 12 5.768Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span&gt;665&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;stat s-hik11q&quot; title=&quot;240 reposts&quot;&gt;&lt;svg class=&quot;icon&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot;&gt;&lt;path stroke=&quot;currentColor&quot; stroke-linecap=&quot;square&quot; stroke-width=&quot;2&quot; d=&quot;m17 3 3 3-3 3M7 21l-3-3 3-3m-2 3h15v-5M4 11V6h15&quot;&gt;&lt;/path&gt;&lt;/svg&gt; &lt;span&gt;240&lt;/span&gt;&lt;/span&gt; &lt;div class=&quot;gap s-hik11q&quot;&gt;&lt;/div&gt; &lt;a href=&quot;https://bsky.app/profile/did:plc:3danwc67lo7obz2fmdg6jxcr/post/3km6y2x6cxk2f&quot; target=&quot;_blank&quot; class=&quot;permalink s-hik11q&quot;&gt;&lt;span&gt;Read 47 replies on Bluesky&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt; &lt;/bluesky-post&gt;
&lt;section data-footnotes class=&quot;footnotes&quot;&gt;&lt;h2 class=&quot;sr-only&quot; id=&quot;footnote-label&quot;&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-1&quot;&gt;
&lt;p&gt;A commentor points out &lt;a href=&quot;https://book.peergos.org/&quot;&gt;https://book.peergos.org/&lt;/a&gt;, which I had not heard of,
but apparently was known to the creators of BlueSky before they made it. Neat. &lt;a href=&quot;#user-content-fnref-1&quot; data-footnote-backref aria-label=&quot;Back to reference 1&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content:encoded></item></channel></rss>