Comparing Community-specs
- Relay Requirements
- New Event Kinds Introduced
- Write Access Control
- Content Type Discovery
- Targeting Publications
- Fetching Community Content
- Comments, Reactions, Labels, Zaps
- Blossom Media
- Infrastructure & Learning Curve
- Migration & Portability
- Conclusion
This is a comparison of 3-4 approaches to communities on Nostr: Communikeys, NIP-72 (including Chorus-style implementations), and Relay-as-Community (using relays themselves as the community container, with Nip-29 rooms as sub-set of that).
NOTE: This article was updated based on comments and things that needed clarification.
Relay Requirements
Communikeys
Works on any standard Nostr relay. No special relay implementation is required. Relays MAY optimize for Communikeys by only storing events from badgeholders, but it’s optional.
NIP-72
Works on standard relays. Uses membership lists (approved, declined, banned) stored as addressable events, plus moderator approval events. See github.com/andotherstuff/chorus for Chorus-style implementations.
Relay-as-Community
The relay itself IS the community. Requires running and maintaining a dedicated relay instance. The relay URL becomes the community identifier. Complex configuration across multiple NIPs:
- NIP-11 for relay metadata (owner pubkey, identity)
- NIP-29 for rooms/groups within the relay
- NIP-42 for authentication and access control
- NIP-43 for member lists and invite codes
- NIP-86 for admin editing capabilities
If the relay goes down, the community is out.
New Event Kinds Introduced
Communikeys
2 event kinds:
kind:10222— Community Definitionkind:30222— Targeted Publication
Uses existing primitives for everything else: badges (NIP-58), forms (NIP-101), profile metadata (kind:0).
NIP-72
11+ event kinds (Chorus-style):
kind:4550— Post approvalkind:4551— Post removalkind:4552— Join requestkind:4553— Leave requestkind:4554— Close reportkind:34550— Community definitionkind:34551— Approved members listkind:34552— Declined members listkind:34553— Banned members listkind:34554— Pinned posts listkind:34555— Pinned groups list
Relay-as-Community
14+ event kinds spread across multiple NIPs:
kind:9— Chat messagekind:9000— Add userkind:9001— Remove userkind:9002— Edit metadatakind:9003— Add permissionkind:9004— Remove permissionkind:9005— Delete eventkind:9006— Edit group statuskind:9021— Join requestkind:9022— Leave requestkind:39000— Group metadatakind:39001— Group adminskind:39002— Group memberskind:39003— Group roles
Plus relay-specific configuration not stored as events (NIP-11, NIP-42, NIP-43, NIP-86).
Write Access Control
Communikeys
Content sections (Chat, Posts, Articles) have specific event kinds and badge requirements. Multiple badges can grant access to the same section. Granular, per-content-type permissions.
Badge requests use Forms (NIP-101), allowing communities to require anything: email verification, captcha, payments, invite codes, questionnaires, etc. All requirements are transparent in the Badge Definition and Form Template events.
NIP-72
Membership lists (approved, declined, banned) control who can participate. Join/leave request system. No content-type-specific permissions — approved members can post anything.
Relay-as-Community
Role-based access managed per relay. Roles grant capabilities (delete, edit, etc.) but definitions are relay-specific and non-standardized. Each relay can define its own roles. Interoperability is difficult — access rules are invisible and vary between relays.
Content Type Discovery
Communikeys
The community definition explicitly lists which content types (event kinds) it handles via content sections. This is an elegant signal: “we are a place for Articles”, “we curate Emoji Packs”, “we host an App Catalog”.
Users and apps can discover communities by content type. Looking for places that publish long-form articles? Query for communities with k:30023. Want to find emoji pack curators? Look for k:30030. App catalogs, book publishers, video channels — all discoverable by their declared content types.
Nothing more, nothing less. You know exactly what a community is about before you look inside.
NIP-72, NIP-29, and Relays
No content type declaration. Communities are generic containers. You don’t know what content types to look for until you’re already inside browsing around. Apps can’t filter communities by specialization. Discovery is manual exploration rather than structured queries.
Targeting Publications
Communikeys
Any existing Nostr event can be targeted to a community via a Targeted Publication event (kind:30222). Full backwards compatibility. The association can be updated or removed without affecting the original content.
A single publication can be targeted to up to 12 communities via one Targeted Publication event. The creator’s intended audience is explicit and transparent — anyone can see which communities a piece of content was meant for. This can serve as an organic disovery route for related Communities + lowers the bar for bootstrapping new ones.
NIP-72 and NIP-29
Events must include the community/group tag (a or h) when created. Content is permanently tied to the community. Cross-posting via reposts is possible but confusing.
The creator’s intent is baked into the original event, but there’s no open-ended “target audience”. Content just belongs to a group.
Relay-as-Community
No targeting mechanism. You just publish to the relay. Content isn’t “targeted” — it’s just there, in the same way it might be on a thousand other relays. No way to express intended audience.
Best you can do is poletly ask the relay to not propagate your publication (with -tag), which goes against one of the main value props of the Nostr protocol.
Fetching Community Content
Communikeys
Per-section REQ query:
- Fetch the profile list (kind:30000) referenced in the content section’s
atag — single event with all whitelisted pubkeys - REQ the content kinds filtered by those pubkeys
No need to query potentially hundreds of badge award events — the profile list gives you all allowed pubkeys in one fetch. Different content sections can have different whitelists, so you only fetch pubkeys relevant to the section you’re viewing. REQ-level filtering, efficient and granular.
NIP-72
- Fetch approved members list (all members)
- REQ content kinds filtered by those member pubkeys
Similar REQ-level filtering, but no per-section granularity. You fetch ALL members for ALL content types.
Relay-as-Community
Just connect to the relay URL. Members are assumed to be allowed there. But this creates a tradeoff:
- Either the relay only stores member events — limiting, since you often want non-member events too
- Or the relay stores everything from anyone
For NIP-29 rooms within a relay, you can REQ by h tag to filter group-specific content. But for the relay-as-community case (the relay itself is the community), you’re stuck with the member-only tradeoff.
Information is also scattered across multiple NIPs (NIP-11, NIP-29, NIP-42, NIP-43).
Comments, Reactions, Labels, Zaps
Communikeys
A standard “General” content section handles comments (kind:1111), reactions (kind:7), and labels (kind:1985) with one shared profile list and badge. Fetch the list, filter responses by those pubkeys.
- Comments, reactions, labels: Filter by the General section’s profile list. Only members’ responses are shown.
- Zaps: Anyone can zap. Query zap receipts on the community relay.
Creators publish once, list the communities they want to target, and members from all those communities meet in one shared comments section. One discussion, multiple communities participating together. No duplicates, no fragmented conversations to check.
NIP-72 and NIP-29 and Relays
Comments and reactions filter by members (Nip-72) or by relay, straightforward.
But with Nip-72 and Nip-29 your content is permanently tied to one community. To reach multiple communities, you must post duplicates. Discussions fragment — creators have to check each community separately for responses to what is essentially the same content.
With just Relays, you don’t even know if you’re in the right place for the discussion.
Blossom Media
Communikeys
Community definition specifies Blossom server(s). Smart community servers can store all media posted in publications based on content hashes — even if the original URLs differ. Media referenced in community content lives on the community’s infrastructure, preventing link rot.
NIP-72
Can specify Blossom servers in community definition (similar capability). Media persistence depends on implementation.
Relay-as-Community
No built-in media solution. Members use their own Blossom servers or external hosting. Media links can rot if members’ servers go offline. No transparent way to announce community media servers without additional conventions.
Infrastructure & Learning Curve
Communikeys
Communikeys piggyback on everything profiles already have or need:
Social graph — the npub already has a social network around it. Servers and services already analyze how profiles link to each other. Communities inherit all of this for free.
Identity with agency — an npub is not just an address, it’s an identifier that can sign things. Attestations flow both ways — to and from the profile. The community can vouch for members, members can vouch for the community. This is fundamentally different from a URL or relay address.
Publishing capabilities — profiles already publish announcements, app recommendations, mute lists, follow lists. Communities get these features automatically. No new specs needed.
Key management solutions — nsec leaking, “this profile is compromised”, “this is my new profile” — these problems are being solved for profiles anyway. Communities using npubs inherit these solutions. NIP-29 and NIP-72 would need to add extra tags or specs to handle community key rotation, compromise recovery, etc.
Badge awarding can be delegated to a separate keypair, allowing assistants or automated systems to handle membership without access to the main community keypair.
NIP-72
Communities are separate addressable events, not tied to a brand’s npub. Loses all the profile-level features. Requires managing membership lists and approval workflows from scratch.
Relay-as-Community
Highest complexity. Must run a relay, configure NIP-11 metadata, set up NIP-42 auth, manage NIP-43 member lists, configure NIP-29 rooms, and enable NIP-86 admin tools. Information is scattered across multiple NIPs.
The relay URL is a DNS-dependent identifier without agency — it can’t sign anything, can’t participate in web-of-trust, can’t be analyzed by social graph tools. Eventually, relay-based communities will need an identity layer anyway to escape DNS dependencies.
Migration & Portability
Communikeys and NIP-72
Portable identifiers. Switch relays by updating your community definition — all references stay intact. Communikeys can also switch blossom servers the same way (and by copying and serving the media based on the hashes).
Relay-as-Community and NIP-29
The relay URL IS the identity. Want to switch hosting? Every reference breaks. Every member’s saved links break. NIP-29 group IDs are relay-scoped — migrate to a new relay and your h-tags are suddenly very confusing, since based on coming across a community event alone, I have no idea where to go look for the new url that works. Same goes for blossom media.
For migration to work in any way smoothly, the community ID would also need to be portable and, thus, sufficiently unique — independent of where it’s hosted. At that point, you might as well use npubs.
Conclusion
If you take the Nip-72, Nip-29 and Relay-as-Community approaches seriously and try to address their limitations, you’d need to add:
-
An identifier with agency — Relays and NIP-29 use URLs as identifiers. URLs can’t sign things, can’t participate in social graphs, can’t be analyzed by web-of-trust tools. You’d have to go look for maybe-up-to-date admin profiles behind them. NIP-72 uses separate addressable events, also without agency. You’d need… an npub.
-
Migration without breaking everything — If your community ID is a relay URL (Relay-as-Community) or tied to a specific relay (NIP-29), switching hosting is a nightmare. All references break. For migration to work smoothly, the ID needs to be portable and sufficiently unique. So why not use an npub anyway?
-
Per-content-type access control — NIP-72, NIP-29, and Relays treat communities as generic containers. No different rules for chat vs articles vs apps. You’d need content sections with kind declarations and badge requirements.
-
Content type discovery — None of these solutions announce which content types they handle. Apps can’t find communities by specialization. You’d need communities to declare which kinds they support.
-
Multi-community targeting — NIP-72 and NIP-29 permanently tie content to one community. Creators fragment discussions across duplicates. You’d need a separate targeting event that can reference multiple communities.
-
Flexible badge-based access — NIP-72 uses approval workflows, NIP-29 uses relay-specific roles. Neither supports forms, payments, invite codes, questionnaires. You’d need badges with form integration.
-
Backup relays — Relay-as-Community and NIP-29 tie you to one server. You’d need relay lists in the community definition.
-
Blossom servers — Relays and NIP-29 have no integrated media solution. You’d need blossom tags.
Follow these paths to their logical conclusions and you arrive at something that looks like Communikeys: communities as npubs, content sections with badge requirements, targeted publications, integrated infrastructure tags.
Communikeys isn’t an alternative to these approaches — it’s what you get when you play them out.
It was pretty amazing to stumble upon those in Flotilla. I’ve started referring to them as breezeway threads… mostly to myself, in my head, anyway 😅
Added Relays-as-groups :Check: . And rewrote a significant part of it, oops. (mostly writing this out for myself anyway, since it’s not part of any communities yet 😉).
Updated this :article: Article pretty hard ngl. Almost made it a new publication, but I still think its the best place for this rewritten text about the exact same subject.
Yeah, it’s just kind 11s on relays, with the relays controlling the access.
i’m in the fiatjaf side of this with the making ACL part of relay business. doesn’t have to be monolithic baked into the relay. i’ve made 4 separate ACL services that do moderation by different mechanisms. currently working on creating a launcher UI that lets you configure which services you want running and update them, also replace modules with custom ones (can be written in any language with protobuf/grpc support).
only nip-29 doesn’t depend on trustworthy clients. depending on trustworthy clients is, quite frankly, extremely naive.
the lack of a defined ACL hierarchy is the mistake with nip-29. as for redundancy, you just make a cluster of them all syncing together with negentropy, which decentralizes it and makes it failure resistant.
i’m surprised nobody has come up with one that doesn’t have any ACL hierarchy and you see what you want to see on the relay, and that it broadcasts it to several relays run by members of the community. everything would be visible by default and your client would have whitelist/blacklist option so you can see what you want to see, or not see what you don’t want to see. people would do their own moderating. i guess nip-01 style twitter clones basically work like this. this is also why clients should allow you to view relay feeds, then you can have relays specialize on a community set of topics.
also, reddit-style discussions were created by @Silberengel in her jumble fork. these are a type of community also, but it’s relay centric i think, iirc.
I agree that “Communikey” is a powerful concept. In fact, I have been thinking and designing around what I call “Shared Identity” in a similar direction as @a9434...885be (i.e., a collective is represented by an npub). We diverge, though, in how we distribute permissions (I drew inspiration from UCANs and capabilities-oriented programming, or CAPs), and how we enforce them (I propose that Relays should be able to authorize requests based on those CAPs, somewhat an extension of NIP-42).
https://npub1vjhrl4k2uj6sttu5y3xahz29esk2nfn274de8qtn5jkv06zwn7gs68ejkd.blossom.band/cbcaa9c5afa7980599c5bd6246b5b881fc372a533d4a159cc48af285cadb8fd9.png
My context is that I am decentralizing an existing software (socialroots.io) and hoping to use Nostr for that. In our case, Collectives create networks of collaboration, so having a first-level (npub) identity is desirable. Regarding your comment on key ownership@3bf0c...a459d, I thought of this in two layers:
I started this repo to document ideas and prototypes: https://github.com/nigini/nostr-collectives, and would appreciate any feedback. (Shout out to @97c70...8e322 and @d0a1f...9a59e who already helped shape some of this.)
That might be true. Let’s see 😉
Yeah, I thought Reposts would do the truck too initially.
But then you’d need to do a repost for each Community you want to target (and ask deletion when you want to retract your publication). This targeting is something you don’t want to use atomic events for though. It makes it hard to get the list of targets in a fast and reliable way. Needs signing of multiple events. Etc… Would be happy to be wrong about this, so correct me where needed.
Or you could do multiple h tags in the repost event or something like that. But then it needs to be editable and that’s then basically how I ended up with Targeted Publications events anyway.
I see. That’s better.
Although I think it raises other issues related to group history and fine-grained moderation. Those types of problems are not immediately obvious to me on NIP-29, but they appeared and ended up making the number of kinds and complexity go up there. I imagine the same stuff would end up happening for Communikeys.
Thanks for the feedback.
I might have misformulated that though (will adjust it to be clearer), and definitely don’t that in my code. Since you can request only events from the pubkey that have the required badge, you avoid the spam issue, even on general relays. Similar to the Chorus member list I guess in a way.
The ID can’t be guaranteed to be unique, and that isn’t a requirement (of course, since the ID is public anyone could just copy it). It just has to be reasonably unique enough to allow a group to move from one relay to another without clashing with other groups in that other relay, within reason.
If the worst happens and the target relay already has a reasonable, real, active group with the same ID then you try moving to a different relay or, as a last resort, run your own relay.
The NIP is bad in many aspects, and the clients so far have been also bad in many ways. There have also been many promising attempts at nice NIP-29 apps but they have all died before completion. I currently have high hopes for https://grimoire.rocks and https://github.com/Nostrord/nostrord.
It wouldn’t be hard to just establish a convention that using a pubkey as the group id in NIP-29 would grant the owner of such pubkey automatic admin powers on any complying relay.
In fact I think @PABLOF7z was working on this exact scheme a while ago.
People creating Nip-29 (aka users) are lost as to how to set them up in a way that actually works around n the apps they use.
In the nip the ID stuff is not clear then, and how is the thing you put after relay address guaranteed to be unique anyway?
And how can you locate “seamlessly”? Is that in there??
I imagine that the strongest feature of Communikeys is that a group is identified by a public key and brands can reuse their existing public keys to create communities, right?
I agree this is a very desirable property, but the problem is that it is not generic enough. Not all communities or internet groups exist around brands, in fact I would guess that most don’t.
And for all the communities that are just a random group of people with some common interest this arrangement isn’t good, as it assumes that one person (or group of people) will “own” that community forever.
Yeah, pomade is very specifically directed at key custody for newbies, and so it won’t really directly apply to other use cases for FROST, but the same technique definitely can be applied in a lot of other ways.
In my mind, the loosest definition of a group is “a place to read and write content”. There are additional things you can have, like rooms, member lists, or access controls, etc. But relays easily fit that basic definition.
Relays have:
Violá, groups!
For illustration, take a look at Flotilla if you haven’t already. To join a group, you simply join a relay.
Some comments on unfounded claims made about NIP-29 in the article:
“Requires a specialized relay that implements group-specific logic. The relay must generate and sign group metadata events, enforce membership rules, handle moderation events, manage roles and permissions, and validate timeline references.”
I agree this is annoying, but isn’t that bad, but it is also very efficient and likely to deliver a much better, faster UX. It also ensures consistency and that messages are delivered in the correct order, which is not something we need in the normal Nostr, but inside a group, specially in a chat room, is important.
“New users must connect to the specific group relay. The relay handles everything, but users still need to understand relay configuration.”
This is not correct. Users don’t have to understand relay configuration to use NIP-29 (or at least not more than they would to use anything else). In fact NIP-29 might be the most “normie-friendly” onboarding experience of all Nostr experiences: it only requires a group address (or clicking a link) and you’re inside, you don’t need to type relay URLs or anything.
“Groups identified by relay-specific IDs. Brands must run their own NIP-29 relay or depend on third-party operators.”
This is also false, groups have IDs and have relays, but the IDs are not tied to the relays, which means that groups can moveto different relays if the original relay becomes evil or goes down, and the migration is seamless as they keep the same ID. In the same way, groups can also fork and keep their history, migrating to a different relay under different moderation.
“If the relay goes down, the group becomes inaccessible.”
Also false, because groups can have fallback relays. And even if they don’t have and their main relay goes down forever the group may be temporarily inaccessible, but it can come back in a different relay and participants can be switched to that new location seamlessly (based on announcements from other members).
The crossposting stuff of Communikeys is cool, but I don’t see why that can’t be easily emulated with a repost or generic repost published inside a NIP-29 group.
Take an event that existed previously, put it inside a group. The effect is the same.
Communikeys cannot work on generic relays either, the relays must be equipped to block posts from people outside the group, otherwise client-side filtering will be overwhelmed by spam.
If a single spammer decides to act then a client will have to download thousands of garbage events that then get filtered out before they find one message that actually belongs to the group.
Haha, yeah. My guts thought when I saw you working on pomade and there’s things was, he’s solving his own argument against #communikeys 😅.
Which, as I said before, is the exact same problem we need to solve for professional keypair use anyway :Check:
I’ll add it too, but it’s almost to vague to even know what properties to list about it. Don’t mean to be arrogant with that, just hard to see the list of things that somehow make the relay a community, how you know what events are targeted at the community, etc… But will try.
You missed relays-as-groups, which simply piggybacks on native relay functionality, introducing 0 new kinds (unless you count nip 43, which is applicable to regular relays too), and supports rooms optionally via nip 29.
By the way, I came up with a possible way to fix my main objection to communikeys, whivh is that the person who generates the key is dictator for life of the group. You might be able to use DKG and FROST signatures to share the community key between admins and rotate the admin list over time. The downside is that admins have to coordinate to sign stuff on behalf of the community, but it could be a big improvement. I vibed a proof of concept: https://github.com/coracle-social/kgroups
@fiatjaf also :pepeD:
Have been waiting for an article like this! Thx.