<rss
      xmlns:atom="http://www.w3.org/2005/Atom"
      xmlns:media="http://search.yahoo.com/mrss/"
      xmlns:content="http://purl.org/rss/1.0/modules/content/"
      xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
      xmlns:dc="http://purl.org/dc/elements/1.1/"
      version="2.0"
    >
      <channel>
        <title><![CDATA[hodlbod]]></title>
        <description><![CDATA[Christian Bitcoiner and developer of the coracle.social nostr client.
Learn more at https://coracle.tools]]></description>
        <link>https://hodlbod.npub.pro/tag/community/</link>
        <atom:link href="https://hodlbod.npub.pro/tag/community/rss/" rel="self" type="application/rss+xml"/>
        <itunes:new-feed-url>https://hodlbod.npub.pro/tag/community/rss/</itunes:new-feed-url>
        <itunes:author><![CDATA[ hodlbod]]></itunes:author>
        <itunes:subtitle><![CDATA[Christian Bitcoiner and developer of the coracle.social nostr client.
Learn more at https://coracle.tools]]></itunes:subtitle>
        <itunes:type>episodic</itunes:type>
        <itunes:owner>
          <itunes:name><![CDATA[ hodlbod]]></itunes:name>
          <itunes:email><![CDATA[ hodlbod]]></itunes:email>
        </itunes:owner>
            
      <pubDate>Thu, 06 Mar 2025 18:38:09 GMT</pubDate>
      <lastBuildDate>Thu, 06 Mar 2025 18:38:09 GMT</lastBuildDate>
      
      <itunes:image href="https://i.nostr.build/AZ0L.jpg" />
      <image>
        <title><![CDATA[hodlbod]]></title>
        <link>https://hodlbod.npub.pro/tag/community/</link>
        <url>https://i.nostr.build/AZ0L.jpg</url>
      </image>
      <item>
      <title><![CDATA[A Guide for Relay-Based Group Implementations]]></title>
      <description><![CDATA[A guide for people who want to build clients for "relays-as-groups" that are compatible with Flotilla and Chachi.]]></description>
             <itunes:subtitle><![CDATA[A guide for people who want to build clients for "relays-as-groups" that are compatible with Flotilla and Chachi.]]></itunes:subtitle>
      <pubDate>Thu, 06 Mar 2025 18:38:09 GMT</pubDate>
      <link>https://hodlbod.npub.pro/post/1741286140797/</link>
      <comments>https://hodlbod.npub.pro/post/1741286140797/</comments>
      <guid isPermaLink="false">naddr1qqxnzde5xyersd33xscrwwfhqgsf03c2gsmx5ef4c9zmxvlew04gdh7u94afnknp33qvv3c94kvwxgsrqsqqqa28l3fvpz</guid>
      <category>nostr</category>
      
        <media:content url="https://coracle-media.us-southeast-1.linodeobjects.com/yaopey-yong-gDT9TyhdT_I-unsplash.jpg" medium="image"/>
        <enclosure 
          url="https://coracle-media.us-southeast-1.linodeobjects.com/yaopey-yong-gDT9TyhdT_I-unsplash.jpg" length="0" 
          type="image/jpeg" 
        />
      <noteId>naddr1qqxnzde5xyersd33xscrwwfhqgsf03c2gsmx5ef4c9zmxvlew04gdh7u94afnknp33qvv3c94kvwxgsrqsqqqa28l3fvpz</noteId>
      <npub>npub1jlrs53pkdfjnts29kveljul2sm0actt6n8dxrrzqcersttvcuv3qdjynqn</npub>
      <dc:creator><![CDATA[ hodlbod]]></dc:creator>
      <content:encoded><![CDATA[<p>When developing on nostr, normally it's enough to read the NIP related to a given feature you want to build to know what has to be done. But there are some aspects of nostr development that aren't so straightforward because they depend less on specific data formats than on how different concepts are combined.</p>
<p>An example of this is how for a while it was considered best practice to re-publish notes when replying to them. This practice emerged before the outbox model gained traction, and was a hacky way of attempting to ensure relays had the full context required for a given note. Over time though, pubkey hints emerged as a better way to ensure other clients could find required context.</p>
<p>Another one of these things is "relay-based groups", or as I prefer to call it "relays-as-groups" (RAG). Such a thing doesn't really exist - there's no spec for it (although some <em>aspects</em> of the concept are included in NIP 29), but at the same time there are two concrete implementations (Flotilla and Chachi) which leverage several different NIPs in order to create a cohesive system for groups on nostr.</p>
<p>This composability is one of the neat qualities of nostr. Not only would it be unhelpful to specify how different parts of the protocol should work together, it would be impossible because of the number of possible combinations possible just from applying a little bit of common sense to the NIPs repo. No one said it was ok to put <code>t</code> tags on a <code>kind 0</code>. But no one's stopping you! And the semantics are basically self-evident if you understand its component parts.</p>
<p>So, instead of writing a NIP that sets relay-based groups in stone, I'm writing this guide in order to document how I've combined different parts of the nostr protocol to create a compelling architecture for groups.</p>
<h2>Relays</h2>
<p>Relays already have a canonical identity, which is the relay's url. Events posted to a relay can be thought of as "posted to that group". This means that every relay is already a group. All nostr notes have already been posted to one or more groups.</p>
<p>One common objection to this structure is that identifying a group with a relay means that groups are dependent on the relay to continue hosting the group. In normal broadcast nostr (which forms organic permissionless groups based on user-centric social clustering), this is a very bad thing, because hosts are orthogonal to group identity. Communities are completely different. Communities actually need someone to enforce community boundaries, implement moderation, etc. Reliance on a host is a feature, not a bug (in contrast to NIP 29 groups, which tend to co-locate many groups on a single host, relays-as-groups tends to encourage one group, one host).</p>
<p>This doesn't mean that federation, mirrors, and migration can't be accomplished. In a sense, leaving this on the social layer is a good thing, because it adds friction to the dissolution/forking of a group. But the door is wide open to protocol additions to support those use cases for relay-based groups. One possible approach would be to follow <a href="https://github.com/coracle-social/nips/blob/60179dfba2a51479c569c9192290bb4cefc660a8/xx.md<a href='/tag/federation/'>#federation</a>">this draft PR</a> which specifies a "federation" event relays could publish on their own behalf.</p>
<h2>Relay keys</h2>
<p><a href="https://github.com/nostr-protocol/nips/pull/1764">This draft PR to NIP 11</a> specifies a <code>self</code> field which represents the relay's identity. Using this, relays can publish events on their own behalf. Currently, the <code>pubkey</code> field sort of does the same thing, but is overloaded as a contact field for the owner of the relay.</p>
<h2>AUTH</h2>
<p>Relays can control access using <a href="https://github.com/nostr-protocol/nips/blob/master/42.md">NIP 42 AUTH</a>. There are any number of modes a relay can operate in:</p>
<ol>
<li>No auth, fully public - anyone can read/write to the group.</li>
<li>Relays may enforce broad or granular access controls with AUTH.</li>
</ol>
<p>Relays may deny EVENTs or REQs depending on user identity. Messages returned in AUTH, CLOSED, or OK messages should be human readable. It's crucial that clients show these error messages to users. Here's how Flotilla handles failed AUTH and denied event publishing:</p>
<p><img src="https://coracle-media.us-southeast-1.linodeobjects.com/2025-03-06-flotilla-publish-failure.mov" alt="Demo"></p>
<p><a href="https://github.com/nostr-protocol/nips/pull/1434">LIMITS</a>, <a href="https://github.com/coracle-social/nips/blob/d3c9020363952cd603111478f4ba99200f96ac75/xx.md">PROBE</a>, or some other reflection scheme could also be used in theory to help clients adapt their interface depending on user abilities and relay policy.</p>
<ol start="3">
<li>AUTH with implicit access controls.</li>
</ol>
<p>In this mode, relays may exclude matching events from REQs if the user does not have permission to view them. This can be useful for multi-use relays that host hidden rooms. This mode should be used with caution, because it can result in confusion for the end user.</p>
<p>See <a href="https://github.com/coracle-social/frith">Frith</a> for a relay implementation that supports some of these auth policies.</p>
<h2>Invite codes</h2>
<p>If a user doesn't have access to a relay, they can request access using <a href="https://github.com/nostr-protocol/nips/pull/1079">this draft NIP</a>. This is true whether access has been explicitly or implicitly denied (although users will have to know that they should use an invite code to request access).</p>
<p>The above referenced NIP also contains a mechanism for users to request an invite code that they can share with other users.</p>
<p>The policy for these invite codes is entirely up to the relay. They may be single-use, multi-use, or require additional verification. Additional requirements can be communicated to the user in the OK message, for example directions to visit an external URL to register.</p>
<p>See <a href="https://github.com/coracle-social/frith">Frith</a> for a relay implementation that supports invite codes.</p>
<h2>Content</h2>
<p>Any kind of event can be published to a relay being treated as a group, unless rejected by the relay implementation. In particular, <a href="https://github.com/nostr-protocol/nips/blob/master/7D.md">NIP 7D</a> was added to support basic threads, and <a href="https://github.com/nostr-protocol/nips/blob/master/C7.md">NIP C7</a> for chat messages.</p>
<p>Since which relay an event came from determines which group it was posted to, clients need to have a mechanism for keeping track of which relay they received an event from, and should not broadcast events to other relays (unless intending to cross-post the content).</p>
<h2>Rooms</h2>
<p>Rooms follow <a href="https://github.com/nostr-protocol/nips/blob/master/29.md">NIP 29</a>. I wish NIP 29 wasn't called "relay based groups", which is very confusing when talking about "relays as groups". It's much better to think of them as sub-groups, or as Flotilla calls them, "rooms".</p>
<p>EDIT: Flotilla has migrated to exclusively use "managed rooms" — i.e., fully NIP 29 compliant rooms. Relays without NIP 29 support can still support chat, but all messages will be presented as sent to a single room. I've removed references to unmanaged rooms in what follows.</p>
<p><del>Rooms have two modes - managed and unmanaged. Managed</del> rooms follow all the rules laid out in NIP 29 about metadata published by the relay and user membership. In either case, rooms are represented by a random room id, and are posted to by including the id in an event's <code>h</code> tag. <del>This allows rooms to switch between managed and unmanaged modes without losing any content.</del></p>
<p>Managed room names come from <code>kind 39000</code> room meta events, <del>but unmanaged rooms don't have these. Instead, room names should come from members' NIP 51 <code>kind 10009</code> membership lists. Tags on these lists should look like this: <code>["group", "groupid", "wss://group.example.com", "Cat lovers"]</code>. If no name can be found for the room (i.e., there aren't any members), the room should be ignored by clients.</del></p>
<p>Rooms present a difficulty for publishing to the relay as a whole, since content with an <code>h</code> tag can't be excluded from requests. <del>Currently, relay-wide posts are h-tagged with <code>_</code> which works for "group" clients, but not more generally. I'm not sure how to solve this other than to ask relays to support negative filters.</del> I have ideas on how to solve this in future iterations of relay-based groups, for example using <a href="https://github.com/coracle-social/nips/blob/c5f5d21c3a6036a5c43c3a521ee1588ba62167c6/xx.md">virtual relays</a> or just a <a href="https://github.com/coracle-social/nips/blob/6622710c02bf657cae15ac7629a5c420f24951b0/xx.md">better rooms spec</a>.</p>
<h2>Cross-posting</h2>
<p>The simplest way to cross-post content from one group (or room) to another, is to quote the original note in whatever event kind is appropriate. For example, a blog post might be quoted in a <code>kind 9</code> to be cross-posted to chat, or in a <code>kind 11</code> to be cross-posted to a thread. <code>kind 16</code> reposts can be used the same way if the reader's client renders reposts.</p>
<p>Posting the original event to multiple relays-as-groups is trivial, since all you have to do is send the event to the relay. Posting to multiple rooms simultaneously by appending multiple <code>h</code> tags is however not recommended, since group relays/clients are incentivised to protect themselves from spam by rejecting events with multiple <code>h</code> tags (similar to how events with multiple <code>t</code> tags are sometimes rejected).</p>
<h2>Privacy</h2>
<p>Currently, it's recommended to include a <a href="https://github.com/nostr-protocol/nips/blob/master/70.md">NIP 70</a> <code>-</code> tag on content posted to relays-as-groups to discourage replication of relay-specific content across the network.</p>
<p>Another slightly stronger approach would be for group relays to strip signatures in order to make events invalid (or at least deniable). For this approach to work, users would have to be able to signal that they trust relays to be honest. We could also <a href="https://github.com/nostr-protocol/nips/pull/1682">use ZkSNARKS</a> to validate signatures in bulk.</p>
<p>In any case, group posts should not be considered "private" in the same way E2EE groups might be. Relays-as-groups should be considered a good fit for low-stakes groups with many members (since trust deteriorates quickly as more people get involved).</p>
<h2>Membership</h2>
<p>There is currently no canonical member list published by relays (except for NIP 29 managed rooms). Instead, users keep track of their own relay and room memberships using <code>kind 10009</code> lists. Relay-level memberships are represented by an <code>r</code> tag containing the relay url, and room-level memberships are represented using a <code>group</code> tag.</p>
<p>Users can choose to advertise their membership in a RAG by using unencrypted tags, or they may keep their membership private by using encrypted tags. Advertised memberships are useful for helping people find groups based on their social graph:</p>
<p><img src="https://coracle-media.us-southeast-1.linodeobjects.com/2025-03-06-flotilla-discover-wot.png" alt="Discover"></p>
<p>User memberships should not be trusted, since they can be published unilaterally by anyone, regardless of actual access, so it's better to think of them as "bookmarked groups" or "favorites". Possible improvements in this area would be the ability to provide proof of access:</p>
<ul>
<li>Relays could publish member lists (although this would sacrifice member privacy)</li>
<li>Relays could support a new command that allows querying a particular member's access status</li>
<li>Relays could provide a proof to the member that they could then choose to publish or not</li>
</ul>
<h2>Moderation</h2>
<p>There are two parts to moderation: reporting and taking action based on these reports.</p>
<p>Reporting is already covered by <a href="https://github.com/nostr-protocol/nips/blob/master/56.md">NIP 56</a>. Clients should be careful about encouraging users to post reports for illegal content under their own identity, since that can itself be illegal. Relays also should not serve reports to users, since that can be used to <em>find</em> rather than address objectionable content.</p>
<p>Reports are only one mechanism for flagging objectionable content. Relay operators and administrators can use whatever heuristics they like to identify and address objectionable content. This might be via automated policies that auto-ban based on reports from high-reputation people, a client that implements <a href="https://github.com/nostr-protocol/nips/blob/master/86.md">NIP 86</a> relay management API, or by some other admin interface.</p>
<p>There's currently no way for moderators of a given relay to be advertised, or for a moderator's client to know that the user is a moderator (so that they can enable UI elements for in-app moderation). This could be addressed via <a href="https://github.com/nostr-protocol/nips/blob/master/11.md">NIP 11</a>, <a href="https://github.com/nostr-protocol/nips/pull/1434">LIMITS</a>, or some other mechanism in the future.</p>
<h2>General best practices</h2>
<p>In general, it's very important when developing a client to assume that the relay has <em>no</em> special support for <em>any</em> of the above features, instead treating all of this stuff as <a href="https://developer.mozilla.org/en-US/docs/Glossary/Progressive_Enhancement">progressive enhancement</a>.</p>
<p>For example, if a user enters an invite code, go ahead and send it to the relay using a <code>kind 28934</code> event. If it's rejected, you know that it didn't work. But if it's accepted, you don't know that it worked - you only know that the relay allowed the user to publish that event. This is helpful, becaues it may imply that the user does indeed have access to the relay. But additional probing may be needed, and reliance on error messages down the road when something else fails unexpectedly is indispensable.</p>
<p>This paradigm may drive some engineers nuts, because it's basically equivalent to coding your clients to reverse-engineer relay support for every feature you want to use. But this is true of nostr as a whole - anyone can put whatever weird stuff in an event and sign it. Clients have to be extremely compliant with Postell's law - doing their absolute best to accept whatever weird data or behavior shows up and handle failure in any situation. Sure, it's annoying, but it's the cost of permissionless development. What it gets us is a completely open-ended protocol, in which anything can be built, and in which every solution is tested by the market.</p>
]]></content:encoded>
      <itunes:author><![CDATA[ hodlbod]]></itunes:author>
      <itunes:summary><![CDATA[<p>When developing on nostr, normally it's enough to read the NIP related to a given feature you want to build to know what has to be done. But there are some aspects of nostr development that aren't so straightforward because they depend less on specific data formats than on how different concepts are combined.</p>
<p>An example of this is how for a while it was considered best practice to re-publish notes when replying to them. This practice emerged before the outbox model gained traction, and was a hacky way of attempting to ensure relays had the full context required for a given note. Over time though, pubkey hints emerged as a better way to ensure other clients could find required context.</p>
<p>Another one of these things is "relay-based groups", or as I prefer to call it "relays-as-groups" (RAG). Such a thing doesn't really exist - there's no spec for it (although some <em>aspects</em> of the concept are included in NIP 29), but at the same time there are two concrete implementations (Flotilla and Chachi) which leverage several different NIPs in order to create a cohesive system for groups on nostr.</p>
<p>This composability is one of the neat qualities of nostr. Not only would it be unhelpful to specify how different parts of the protocol should work together, it would be impossible because of the number of possible combinations possible just from applying a little bit of common sense to the NIPs repo. No one said it was ok to put <code>t</code> tags on a <code>kind 0</code>. But no one's stopping you! And the semantics are basically self-evident if you understand its component parts.</p>
<p>So, instead of writing a NIP that sets relay-based groups in stone, I'm writing this guide in order to document how I've combined different parts of the nostr protocol to create a compelling architecture for groups.</p>
<h2>Relays</h2>
<p>Relays already have a canonical identity, which is the relay's url. Events posted to a relay can be thought of as "posted to that group". This means that every relay is already a group. All nostr notes have already been posted to one or more groups.</p>
<p>One common objection to this structure is that identifying a group with a relay means that groups are dependent on the relay to continue hosting the group. In normal broadcast nostr (which forms organic permissionless groups based on user-centric social clustering), this is a very bad thing, because hosts are orthogonal to group identity. Communities are completely different. Communities actually need someone to enforce community boundaries, implement moderation, etc. Reliance on a host is a feature, not a bug (in contrast to NIP 29 groups, which tend to co-locate many groups on a single host, relays-as-groups tends to encourage one group, one host).</p>
<p>This doesn't mean that federation, mirrors, and migration can't be accomplished. In a sense, leaving this on the social layer is a good thing, because it adds friction to the dissolution/forking of a group. But the door is wide open to protocol additions to support those use cases for relay-based groups. One possible approach would be to follow <a href="https://github.com/coracle-social/nips/blob/60179dfba2a51479c569c9192290bb4cefc660a8/xx.md<a href='/tag/federation/'>#federation</a>">this draft PR</a> which specifies a "federation" event relays could publish on their own behalf.</p>
<h2>Relay keys</h2>
<p><a href="https://github.com/nostr-protocol/nips/pull/1764">This draft PR to NIP 11</a> specifies a <code>self</code> field which represents the relay's identity. Using this, relays can publish events on their own behalf. Currently, the <code>pubkey</code> field sort of does the same thing, but is overloaded as a contact field for the owner of the relay.</p>
<h2>AUTH</h2>
<p>Relays can control access using <a href="https://github.com/nostr-protocol/nips/blob/master/42.md">NIP 42 AUTH</a>. There are any number of modes a relay can operate in:</p>
<ol>
<li>No auth, fully public - anyone can read/write to the group.</li>
<li>Relays may enforce broad or granular access controls with AUTH.</li>
</ol>
<p>Relays may deny EVENTs or REQs depending on user identity. Messages returned in AUTH, CLOSED, or OK messages should be human readable. It's crucial that clients show these error messages to users. Here's how Flotilla handles failed AUTH and denied event publishing:</p>
<p><img src="https://coracle-media.us-southeast-1.linodeobjects.com/2025-03-06-flotilla-publish-failure.mov" alt="Demo"></p>
<p><a href="https://github.com/nostr-protocol/nips/pull/1434">LIMITS</a>, <a href="https://github.com/coracle-social/nips/blob/d3c9020363952cd603111478f4ba99200f96ac75/xx.md">PROBE</a>, or some other reflection scheme could also be used in theory to help clients adapt their interface depending on user abilities and relay policy.</p>
<ol start="3">
<li>AUTH with implicit access controls.</li>
</ol>
<p>In this mode, relays may exclude matching events from REQs if the user does not have permission to view them. This can be useful for multi-use relays that host hidden rooms. This mode should be used with caution, because it can result in confusion for the end user.</p>
<p>See <a href="https://github.com/coracle-social/frith">Frith</a> for a relay implementation that supports some of these auth policies.</p>
<h2>Invite codes</h2>
<p>If a user doesn't have access to a relay, they can request access using <a href="https://github.com/nostr-protocol/nips/pull/1079">this draft NIP</a>. This is true whether access has been explicitly or implicitly denied (although users will have to know that they should use an invite code to request access).</p>
<p>The above referenced NIP also contains a mechanism for users to request an invite code that they can share with other users.</p>
<p>The policy for these invite codes is entirely up to the relay. They may be single-use, multi-use, or require additional verification. Additional requirements can be communicated to the user in the OK message, for example directions to visit an external URL to register.</p>
<p>See <a href="https://github.com/coracle-social/frith">Frith</a> for a relay implementation that supports invite codes.</p>
<h2>Content</h2>
<p>Any kind of event can be published to a relay being treated as a group, unless rejected by the relay implementation. In particular, <a href="https://github.com/nostr-protocol/nips/blob/master/7D.md">NIP 7D</a> was added to support basic threads, and <a href="https://github.com/nostr-protocol/nips/blob/master/C7.md">NIP C7</a> for chat messages.</p>
<p>Since which relay an event came from determines which group it was posted to, clients need to have a mechanism for keeping track of which relay they received an event from, and should not broadcast events to other relays (unless intending to cross-post the content).</p>
<h2>Rooms</h2>
<p>Rooms follow <a href="https://github.com/nostr-protocol/nips/blob/master/29.md">NIP 29</a>. I wish NIP 29 wasn't called "relay based groups", which is very confusing when talking about "relays as groups". It's much better to think of them as sub-groups, or as Flotilla calls them, "rooms".</p>
<p>EDIT: Flotilla has migrated to exclusively use "managed rooms" — i.e., fully NIP 29 compliant rooms. Relays without NIP 29 support can still support chat, but all messages will be presented as sent to a single room. I've removed references to unmanaged rooms in what follows.</p>
<p><del>Rooms have two modes - managed and unmanaged. Managed</del> rooms follow all the rules laid out in NIP 29 about metadata published by the relay and user membership. In either case, rooms are represented by a random room id, and are posted to by including the id in an event's <code>h</code> tag. <del>This allows rooms to switch between managed and unmanaged modes without losing any content.</del></p>
<p>Managed room names come from <code>kind 39000</code> room meta events, <del>but unmanaged rooms don't have these. Instead, room names should come from members' NIP 51 <code>kind 10009</code> membership lists. Tags on these lists should look like this: <code>["group", "groupid", "wss://group.example.com", "Cat lovers"]</code>. If no name can be found for the room (i.e., there aren't any members), the room should be ignored by clients.</del></p>
<p>Rooms present a difficulty for publishing to the relay as a whole, since content with an <code>h</code> tag can't be excluded from requests. <del>Currently, relay-wide posts are h-tagged with <code>_</code> which works for "group" clients, but not more generally. I'm not sure how to solve this other than to ask relays to support negative filters.</del> I have ideas on how to solve this in future iterations of relay-based groups, for example using <a href="https://github.com/coracle-social/nips/blob/c5f5d21c3a6036a5c43c3a521ee1588ba62167c6/xx.md">virtual relays</a> or just a <a href="https://github.com/coracle-social/nips/blob/6622710c02bf657cae15ac7629a5c420f24951b0/xx.md">better rooms spec</a>.</p>
<h2>Cross-posting</h2>
<p>The simplest way to cross-post content from one group (or room) to another, is to quote the original note in whatever event kind is appropriate. For example, a blog post might be quoted in a <code>kind 9</code> to be cross-posted to chat, or in a <code>kind 11</code> to be cross-posted to a thread. <code>kind 16</code> reposts can be used the same way if the reader's client renders reposts.</p>
<p>Posting the original event to multiple relays-as-groups is trivial, since all you have to do is send the event to the relay. Posting to multiple rooms simultaneously by appending multiple <code>h</code> tags is however not recommended, since group relays/clients are incentivised to protect themselves from spam by rejecting events with multiple <code>h</code> tags (similar to how events with multiple <code>t</code> tags are sometimes rejected).</p>
<h2>Privacy</h2>
<p>Currently, it's recommended to include a <a href="https://github.com/nostr-protocol/nips/blob/master/70.md">NIP 70</a> <code>-</code> tag on content posted to relays-as-groups to discourage replication of relay-specific content across the network.</p>
<p>Another slightly stronger approach would be for group relays to strip signatures in order to make events invalid (or at least deniable). For this approach to work, users would have to be able to signal that they trust relays to be honest. We could also <a href="https://github.com/nostr-protocol/nips/pull/1682">use ZkSNARKS</a> to validate signatures in bulk.</p>
<p>In any case, group posts should not be considered "private" in the same way E2EE groups might be. Relays-as-groups should be considered a good fit for low-stakes groups with many members (since trust deteriorates quickly as more people get involved).</p>
<h2>Membership</h2>
<p>There is currently no canonical member list published by relays (except for NIP 29 managed rooms). Instead, users keep track of their own relay and room memberships using <code>kind 10009</code> lists. Relay-level memberships are represented by an <code>r</code> tag containing the relay url, and room-level memberships are represented using a <code>group</code> tag.</p>
<p>Users can choose to advertise their membership in a RAG by using unencrypted tags, or they may keep their membership private by using encrypted tags. Advertised memberships are useful for helping people find groups based on their social graph:</p>
<p><img src="https://coracle-media.us-southeast-1.linodeobjects.com/2025-03-06-flotilla-discover-wot.png" alt="Discover"></p>
<p>User memberships should not be trusted, since they can be published unilaterally by anyone, regardless of actual access, so it's better to think of them as "bookmarked groups" or "favorites". Possible improvements in this area would be the ability to provide proof of access:</p>
<ul>
<li>Relays could publish member lists (although this would sacrifice member privacy)</li>
<li>Relays could support a new command that allows querying a particular member's access status</li>
<li>Relays could provide a proof to the member that they could then choose to publish or not</li>
</ul>
<h2>Moderation</h2>
<p>There are two parts to moderation: reporting and taking action based on these reports.</p>
<p>Reporting is already covered by <a href="https://github.com/nostr-protocol/nips/blob/master/56.md">NIP 56</a>. Clients should be careful about encouraging users to post reports for illegal content under their own identity, since that can itself be illegal. Relays also should not serve reports to users, since that can be used to <em>find</em> rather than address objectionable content.</p>
<p>Reports are only one mechanism for flagging objectionable content. Relay operators and administrators can use whatever heuristics they like to identify and address objectionable content. This might be via automated policies that auto-ban based on reports from high-reputation people, a client that implements <a href="https://github.com/nostr-protocol/nips/blob/master/86.md">NIP 86</a> relay management API, or by some other admin interface.</p>
<p>There's currently no way for moderators of a given relay to be advertised, or for a moderator's client to know that the user is a moderator (so that they can enable UI elements for in-app moderation). This could be addressed via <a href="https://github.com/nostr-protocol/nips/blob/master/11.md">NIP 11</a>, <a href="https://github.com/nostr-protocol/nips/pull/1434">LIMITS</a>, or some other mechanism in the future.</p>
<h2>General best practices</h2>
<p>In general, it's very important when developing a client to assume that the relay has <em>no</em> special support for <em>any</em> of the above features, instead treating all of this stuff as <a href="https://developer.mozilla.org/en-US/docs/Glossary/Progressive_Enhancement">progressive enhancement</a>.</p>
<p>For example, if a user enters an invite code, go ahead and send it to the relay using a <code>kind 28934</code> event. If it's rejected, you know that it didn't work. But if it's accepted, you don't know that it worked - you only know that the relay allowed the user to publish that event. This is helpful, becaues it may imply that the user does indeed have access to the relay. But additional probing may be needed, and reliance on error messages down the road when something else fails unexpectedly is indispensable.</p>
<p>This paradigm may drive some engineers nuts, because it's basically equivalent to coding your clients to reverse-engineer relay support for every feature you want to use. But this is true of nostr as a whole - anyone can put whatever weird stuff in an event and sign it. Clients have to be extremely compliant with Postell's law - doing their absolute best to accept whatever weird data or behavior shows up and handle failure in any situation. Sure, it's annoying, but it's the cost of permissionless development. What it gets us is a completely open-ended protocol, in which anything can be built, and in which every solution is tested by the market.</p>
]]></itunes:summary>
      <itunes:image href="https://coracle-media.us-southeast-1.linodeobjects.com/yaopey-yong-gDT9TyhdT_I-unsplash.jpg"/>
      </item>
      
      <item>
      <title><![CDATA[A Vision for Nostr]]></title>
      <description><![CDATA[What Mastodon got wrong, and what I hope Nostr gets right]]></description>
             <itunes:subtitle><![CDATA[What Mastodon got wrong, and what I hope Nostr gets right]]></itunes:subtitle>
      <pubDate>Wed, 29 Mar 2023 19:55:14 GMT</pubDate>
      <link>https://hodlbod.npub.pro/post/a-vision-for-nostr/</link>
      <comments>https://hodlbod.npub.pro/post/a-vision-for-nostr/</comments>
      <guid isPermaLink="false">naddr1qqfxzttkd9ekjmmw94nx7u3ddehhxarjqgsf03c2gsmx5ef4c9zmxvlew04gdh7u94afnknp33qvv3c94kvwxgsrqsqqqa2807nk73</guid>
      <category>nostr</category>
      
        <media:content url="https://coracle.us-southeast-1.linodeobjects.com/juniperphoton-_lwLalY6Yzg-unsplash.jpeg" medium="image"/>
        <enclosure 
          url="https://coracle.us-southeast-1.linodeobjects.com/juniperphoton-_lwLalY6Yzg-unsplash.jpeg" length="0" 
          type="image/jpeg" 
        />
      <noteId>naddr1qqfxzttkd9ekjmmw94nx7u3ddehhxarjqgsf03c2gsmx5ef4c9zmxvlew04gdh7u94afnknp33qvv3c94kvwxgsrqsqqqa2807nk73</noteId>
      <npub>npub1jlrs53pkdfjnts29kveljul2sm0actt6n8dxrrzqcersttvcuv3qdjynqn</npub>
      <dc:creator><![CDATA[ hodlbod]]></dc:creator>
      <content:encoded><![CDATA[<p>"What is Nostr?" is a hard question to answer. But an even more difficult one is "what should Nostr be?" Set aside the fact that "other stuff" is making up an ever-growing share of Nostr applications, even the social media use case on its own is a fractal of a problem.</p>
<p>What's encouraging though, is that despite the complexity of "social media", there is a surprising level of consensus on what needs to be done - within the Nostr developer community, differences are characterized more by emphasis than by direction.</p>
<h1>Staying on mission</h1>
<p>Instead of focusing on "problems to be solved" within the current system (e.g. content monetization or data harvesting), people who "get" nostr have made its core principles their own. Because these principles radically differ from the way things are done in centralized systems, they spawn a complex system of new affordances and limitations.</p>
<p>If I had to sum up what the core principle of Nostr is, I would say "individual sovereignty". Nostr is a social experiment that asks people to take responsibility for what they say (and sell, host, publish, promote). This topic has been explored ad nauseum by <a href="https://dergigi.com/2019/08/22/the-rise-of-the-sovereign-individual/">better writers than I</a> using Bitcoin as a vehicle, so I'll avoid re-treading the same ground if I can, except to point out that the two key design decisions of the Nostr protocol, self-custody of keys and hosting spread across multiple relays, simultaneously entrust control to users and revoke certain entitlements users are accustomed to.</p>
<p>It's well- (maybe even over-) understood what the risks and benefits are of holding your own keys. And being able to either select or host your own relays, each with different purposes and characteristics, gives individuals a level of control over his own publishing platform precedented only by the World Wide Web itself.</p>
<h1>Lies they tell</h1>
<p>But there are a lot of things users lose when moving away from a centralized platform. The ability to edit, delete, block, and promote content are not what I'm talking about - the guarantees for being able to do these things on Nostr are weaker, but as long as someone can take a screenshot of your Tweet, or block Google's ads, or log in with a different account, the affordances provided by centralized platforms are conveniences at best, and illusory at worst - that is, unless we go full digital panopticon, with universal biometric authentication and DRM for our brains.</p>
<p>What is more interesting to me is how centralized social media platforms lie about what they essentially are. Twitter's motto is "what’s happening", and their <a href="https://about.twitter.com/en">about page</a> features a tweet encouraging others to "Speak the truth, even if your voice shakes." And yet over the last several years they have censored real news, promoted propaganda, and shadow banned those whose "voice shakes". Musk's desperate claims that "we'll stop, I promise" don't negate the fact that Twitter retains control over users' speech in a way that is inherently in conflict with their stated mission.</p>
<p>This is true even of non-political speech, because it is in Twitter's interest to promote content that drives engagement, because engagement is what in turn drives advertising profits. This undermines their claim of user enfranchisement - they exercise partiality in choosing whose voice gets a megaphone.</p>
<p>Users of Nostr know the feeling of this weight being lifted. Nostr is anything but polished, but that's part of the charm - you know there is no one scanning your content, deciding who sees what and with what "added context". Many users including myself have experienced a 10x or more increase in engagement, despite a much smaller number of people on the platform. This is of course likely due not only to the lack of an algorithm, but also to the lack of celebrities, which tend to absorb attention, leaving little for the rest of us. But for now, Nostr is for the plebs.</p>
<h1>Cutting the Gordian Knot</h1>
<p>And I hope, and have reason, that it will continue to be so. When I spoke to my pastor prior to moving to Austin to work on Coracle full-time, I asked him what problems related to social media he would like to see solved. He said that he would like to see a solution that puts users in control of their algorithm, and allows individuals to broadcast their content to as wide an audience as possible.</p>
<p>There is a contradiction here, and the claim that it can be solved is one of the main lies that centralized platforms like to tell. You are free to broadcast your data as widely as you want, but no one is obligated to read it. Twitter tries to square the circle by artificially reversing this trade-off, resulting in a system where "you can't broadcast your data unless we want to force people to read it." But even they can't give their users control while simultaneously taking it away.</p>
<p>There is a path forward though, and now we finally get to the point of this post. Nostr is so revolutionary because it puts "digital localism" within reach. I had better define my terms here, since "digital localism" is used to describe a lot of dystopian ideas I'm not very excited about. What I mean by the term is something like "social relevance". Contra the egalitarians, there are real differences that exist to set groups of people apart. Things like topical interest, physical geography, professional network, religious belief, and yes, ethnicity and sex.</p>
<h1>What is a community anyway</h1>
<p>The fact that digital "communties" exist is something that to their credit Mastodon recognized, and sought to accommodate. But they missed the fact that humanity is partitioned into a nearly infinite number of overlapping sub-groups based on a nearly infinite number of dimensions. Yes, maybe I should be friends with you because you also like cats, but let's refine this further, do you think cilantro tastes like soap, are you a member of the Church of Satan, are you Italian, have you been reading Hayak lately, do you like watching Hallmark movies, English, do you speak it? Partitioning people into groups based on a single dimension is an exercise in futility, and is the reason Mastodon instances are either ghost towns or home to millions of users.</p>
<p>By allowing users to download/host their own data and join as many and whichever relays they choose based on arbitrary criteria, people are now able to co-locate in digital space, and interact with each instance in a different way. This is why I'm not excited about tools that spray your data to as many relays as possible. This only serves to maintain the illusion that replicating all content across every instance can scale, and it can't.</p>
<p>Instead, relays should differentiate, both in terms of function and membership. In the future (and even now) there will be closed archival relays that scrape the network and provide a backup of user data for a fee; public-read, private-write relays that allow members to participate in an exclusive group with greater reach; private-read, private-write closed community relays; public "town square" relays, paid relays that provide indexes, full-text search, or content recommendations for the wider network (or a relevant subset of it); and relays that provide oracles for data external to nostr. The ability of users to pick and choose which relays to connect to (and to multiplex those connections through yet another proxy/aggregator relay) allows them to define their own low-granularity social graph, refining it further with follows, mutes, and other "algorithmic" tools.</p>
<p>The same is true of client implementations. Many people building social media platforms want to "fix Twitter". But that vision of digital society is amazingly narrow (luckily, Nostr developers don't seem to suffer from the same kind of myopia). <em>Most</em> people I know don't have Twitter accounts, or use them. For them, Twitter is about as relevant to their lives as CNN. Instead, they use private Facebook groups to arrange babysitters for their kids, or Cragislist to buy and sell local goods. They use Google maps to find reviews for nearby businesses, and the church email list to keep up with prayer requests. They subscribe to newsletters their friends publish, and spend their days at work sending memes over Slack. The common theme here is that all these platforms connect "us" with "mine", not with "them". And yes, journalism and topical interest ala Reddit is a part of this, but for normal people, a vanishingly small part. But let's stop squawking about "echo chambers".</p>
<p>And Nostr, <a href="https://blog.coracle.social/what-nostr-is-bad-at.html">despite its limitations</a>, can be applied to every use case enumerated above. In so doing, it will free regular people from the constraining force of opinionated, artificial, centralized communication platforms, and allow them to build a digital social network that complements real life.</p>
<h1>Conclusion</h1>
<p>The driving force, for me, is not to erase our differences and create an egalitarian utopia, or stick it to big tech, or to make money, but to see the people I love, who belong to me, and to whom I belong, flourish by being connected with the people who belong to them, and to whom they belong. The resulting network will be characterized by high trust and high cohesion, laying a solid foundation for content and ideas to efficiently propagate across the distributed social graph, similar to how the lightning network routes transactions. But the key to making this work is to rise to the occasion, and take back our digital sovereignty by making it as easy for the average person to navigate the digital social landscape as they do in real life.</p>
]]></content:encoded>
      <itunes:author><![CDATA[ hodlbod]]></itunes:author>
      <itunes:summary><![CDATA[<p>"What is Nostr?" is a hard question to answer. But an even more difficult one is "what should Nostr be?" Set aside the fact that "other stuff" is making up an ever-growing share of Nostr applications, even the social media use case on its own is a fractal of a problem.</p>
<p>What's encouraging though, is that despite the complexity of "social media", there is a surprising level of consensus on what needs to be done - within the Nostr developer community, differences are characterized more by emphasis than by direction.</p>
<h1>Staying on mission</h1>
<p>Instead of focusing on "problems to be solved" within the current system (e.g. content monetization or data harvesting), people who "get" nostr have made its core principles their own. Because these principles radically differ from the way things are done in centralized systems, they spawn a complex system of new affordances and limitations.</p>
<p>If I had to sum up what the core principle of Nostr is, I would say "individual sovereignty". Nostr is a social experiment that asks people to take responsibility for what they say (and sell, host, publish, promote). This topic has been explored ad nauseum by <a href="https://dergigi.com/2019/08/22/the-rise-of-the-sovereign-individual/">better writers than I</a> using Bitcoin as a vehicle, so I'll avoid re-treading the same ground if I can, except to point out that the two key design decisions of the Nostr protocol, self-custody of keys and hosting spread across multiple relays, simultaneously entrust control to users and revoke certain entitlements users are accustomed to.</p>
<p>It's well- (maybe even over-) understood what the risks and benefits are of holding your own keys. And being able to either select or host your own relays, each with different purposes and characteristics, gives individuals a level of control over his own publishing platform precedented only by the World Wide Web itself.</p>
<h1>Lies they tell</h1>
<p>But there are a lot of things users lose when moving away from a centralized platform. The ability to edit, delete, block, and promote content are not what I'm talking about - the guarantees for being able to do these things on Nostr are weaker, but as long as someone can take a screenshot of your Tweet, or block Google's ads, or log in with a different account, the affordances provided by centralized platforms are conveniences at best, and illusory at worst - that is, unless we go full digital panopticon, with universal biometric authentication and DRM for our brains.</p>
<p>What is more interesting to me is how centralized social media platforms lie about what they essentially are. Twitter's motto is "what’s happening", and their <a href="https://about.twitter.com/en">about page</a> features a tweet encouraging others to "Speak the truth, even if your voice shakes." And yet over the last several years they have censored real news, promoted propaganda, and shadow banned those whose "voice shakes". Musk's desperate claims that "we'll stop, I promise" don't negate the fact that Twitter retains control over users' speech in a way that is inherently in conflict with their stated mission.</p>
<p>This is true even of non-political speech, because it is in Twitter's interest to promote content that drives engagement, because engagement is what in turn drives advertising profits. This undermines their claim of user enfranchisement - they exercise partiality in choosing whose voice gets a megaphone.</p>
<p>Users of Nostr know the feeling of this weight being lifted. Nostr is anything but polished, but that's part of the charm - you know there is no one scanning your content, deciding who sees what and with what "added context". Many users including myself have experienced a 10x or more increase in engagement, despite a much smaller number of people on the platform. This is of course likely due not only to the lack of an algorithm, but also to the lack of celebrities, which tend to absorb attention, leaving little for the rest of us. But for now, Nostr is for the plebs.</p>
<h1>Cutting the Gordian Knot</h1>
<p>And I hope, and have reason, that it will continue to be so. When I spoke to my pastor prior to moving to Austin to work on Coracle full-time, I asked him what problems related to social media he would like to see solved. He said that he would like to see a solution that puts users in control of their algorithm, and allows individuals to broadcast their content to as wide an audience as possible.</p>
<p>There is a contradiction here, and the claim that it can be solved is one of the main lies that centralized platforms like to tell. You are free to broadcast your data as widely as you want, but no one is obligated to read it. Twitter tries to square the circle by artificially reversing this trade-off, resulting in a system where "you can't broadcast your data unless we want to force people to read it." But even they can't give their users control while simultaneously taking it away.</p>
<p>There is a path forward though, and now we finally get to the point of this post. Nostr is so revolutionary because it puts "digital localism" within reach. I had better define my terms here, since "digital localism" is used to describe a lot of dystopian ideas I'm not very excited about. What I mean by the term is something like "social relevance". Contra the egalitarians, there are real differences that exist to set groups of people apart. Things like topical interest, physical geography, professional network, religious belief, and yes, ethnicity and sex.</p>
<h1>What is a community anyway</h1>
<p>The fact that digital "communties" exist is something that to their credit Mastodon recognized, and sought to accommodate. But they missed the fact that humanity is partitioned into a nearly infinite number of overlapping sub-groups based on a nearly infinite number of dimensions. Yes, maybe I should be friends with you because you also like cats, but let's refine this further, do you think cilantro tastes like soap, are you a member of the Church of Satan, are you Italian, have you been reading Hayak lately, do you like watching Hallmark movies, English, do you speak it? Partitioning people into groups based on a single dimension is an exercise in futility, and is the reason Mastodon instances are either ghost towns or home to millions of users.</p>
<p>By allowing users to download/host their own data and join as many and whichever relays they choose based on arbitrary criteria, people are now able to co-locate in digital space, and interact with each instance in a different way. This is why I'm not excited about tools that spray your data to as many relays as possible. This only serves to maintain the illusion that replicating all content across every instance can scale, and it can't.</p>
<p>Instead, relays should differentiate, both in terms of function and membership. In the future (and even now) there will be closed archival relays that scrape the network and provide a backup of user data for a fee; public-read, private-write relays that allow members to participate in an exclusive group with greater reach; private-read, private-write closed community relays; public "town square" relays, paid relays that provide indexes, full-text search, or content recommendations for the wider network (or a relevant subset of it); and relays that provide oracles for data external to nostr. The ability of users to pick and choose which relays to connect to (and to multiplex those connections through yet another proxy/aggregator relay) allows them to define their own low-granularity social graph, refining it further with follows, mutes, and other "algorithmic" tools.</p>
<p>The same is true of client implementations. Many people building social media platforms want to "fix Twitter". But that vision of digital society is amazingly narrow (luckily, Nostr developers don't seem to suffer from the same kind of myopia). <em>Most</em> people I know don't have Twitter accounts, or use them. For them, Twitter is about as relevant to their lives as CNN. Instead, they use private Facebook groups to arrange babysitters for their kids, or Cragislist to buy and sell local goods. They use Google maps to find reviews for nearby businesses, and the church email list to keep up with prayer requests. They subscribe to newsletters their friends publish, and spend their days at work sending memes over Slack. The common theme here is that all these platforms connect "us" with "mine", not with "them". And yes, journalism and topical interest ala Reddit is a part of this, but for normal people, a vanishingly small part. But let's stop squawking about "echo chambers".</p>
<p>And Nostr, <a href="https://blog.coracle.social/what-nostr-is-bad-at.html">despite its limitations</a>, can be applied to every use case enumerated above. In so doing, it will free regular people from the constraining force of opinionated, artificial, centralized communication platforms, and allow them to build a digital social network that complements real life.</p>
<h1>Conclusion</h1>
<p>The driving force, for me, is not to erase our differences and create an egalitarian utopia, or stick it to big tech, or to make money, but to see the people I love, who belong to me, and to whom I belong, flourish by being connected with the people who belong to them, and to whom they belong. The resulting network will be characterized by high trust and high cohesion, laying a solid foundation for content and ideas to efficiently propagate across the distributed social graph, similar to how the lightning network routes transactions. But the key to making this work is to rise to the occasion, and take back our digital sovereignty by making it as easy for the average person to navigate the digital social landscape as they do in real life.</p>
]]></itunes:summary>
      <itunes:image href="https://coracle.us-southeast-1.linodeobjects.com/juniperphoton-_lwLalY6Yzg-unsplash.jpeg"/>
      </item>
      
      </channel>
      </rss>
    