Nostr Community Conventions: A Layer Between NIPs and Application Design

Nostr has strong protocol primitives, but primitives alone do not guarantee interoperability.

Two applications can both use valid Nostr events, valid signatures and valid relays, yet still be unable to understand each other because they chose different ways to represent the same higher-level idea.

That problem becomes more common as the ecosystem grows. Service discovery, operator authority, capability declarations, software releases and trust policy can all be built with existing Nostr tools, but without shared conventions each project is likely to invent its own structure.

At that point, the ecosystem is not short of protocol features. It is short of agreement.

NIPs are the right mechanism for defining protocol behaviour and broadly reusable protocol extensions. They cover things such as event formats, relay behaviour, encryption, addressing, Git collaboration, file metadata and lists.

But not every interoperability problem belongs in the protocol.

There is a large space between “this should become part of Nostr” and “every application should solve this independently.” Nostr Community Conventions, or NCCs, are intended to sit in that space.

What is an NCC?

An NCC is a shared convention for building on top of existing Nostr primitives. It does not change relay behaviour, require a new transport, or need every Nostr client to understand it. It provides a common structure that different applications can recognise when they are solving the same kind of problem.

Nostr already gives us signed events, addressable events, pubkeys, tags, encryption and relay distribution. Those primitives are enough to build service discovery, describe service capabilities, delegate limited operational authority, publish operational state and represent software releases.

The problem starts when every project creates its own event layout and interpretation for the same concept. NCCs are intended to reduce that fragmentation.

How is that different from a NIP?

A NIP describes part of the Nostr protocol or a broadly reusable protocol extension. An NCC describes how applications can compose existing pieces into a higher-level convention.

A useful way to think about it is:

NIPs
define the primitives

NCCs
define shared ways to compose them

Applications
decide whether to use them

NCCs are intentionally optional. A relay should not need to know that an NCC exists, and ordinary Nostr behaviour should continue unchanged if a particular NCC is ignored.

A proposal that requires relay changes, changes the meaning of an existing NIP, or introduces behaviour that really belongs in the core protocol probably should not be an NCC. At the other end, something specific to one application, with no expectation that other software will interpret it, probably does not need an NCC either.

NCCs are aimed at the layer between those two cases.

What kind of problems are NCCs trying to solve?

The current work has mostly focused on services and software.

Service identity and trust allows a service to be anchored to a Nostr identity rather than being defined only by a hostname.

Service location allows that identity to publish where the service is currently reachable without making DNS the root of its identity.

Capability discovery gives services a common way to declare which NIPs, NCCs or application-specific capabilities they support.

Identity rotation gives long-lived services a way to move from one key to another while preserving continuity.

Scoped operator authority allows a service to authorise another key for a narrow task without handing over the root identity. A deployment system might be allowed to publish operational state while having no authority to rotate the service identity.

Operational state gives services a simple way to report that they are operational, degraded, under maintenance, unavailable or retiring.

Portable trust policy allows a client or runtime to carry its trust preferences between applications instead of configuring the same rules repeatedly.

Software distribution can build on existing Nostr release objects and add package-manager semantics such as versioning, dependencies, platform compatibility and release channels.

Most of these do not need new network behaviour. They are conventions around events Nostr already knows how to store and distribute.

Why not just put all of this into NIPs?

Making everything a protocol concern has a cost. Nostr benefits from having a relatively small set of primitives that can be reused in different ways, and pushing every application pattern into a NIP gradually makes the protocol responsible for decisions that could have remained at the application layer.

There is also value in trying ideas before deciding whether they deserve broader standardisation. An NCC can be implemented by a few projects, changed, discarded, split up or simplified without implying that the Nostr protocol itself is changing.

If an NCC eventually proves broadly useful enough that part of it belongs in a NIP, that path remains open. NCCs are not intended to compete with NIPs. They provide a place to work on shared conventions below that threshold.

Why should anyone care?

Interoperability problems tend to appear slowly. At first, every application has a reasonable local solution. One service uses one capability format, another uses a different one, several clients represent operator authority differently, and two package managers describe dependencies in incompatible ways.

Each implementation can work perfectly well on its own. The problem appears when those systems need to understand each other, because each project has effectively created its own small protocol.

Shared conventions reduce that cost and make it easier for different parts of the Nostr ecosystem to compose. A client given a service pubkey could potentially determine what service it represents, where it can be reached, what it supports, whether an operator is authorised to act for it, whether it is under maintenance, and whether its identity has moved to another key.

A package manager could consume software releases published through ordinary Nostr events without depending on a central package registry to define their identity. That is the kind of interoperability NCCs are intended to support.

They are not rules

The word “convention” is deliberate. An NCC does not gain authority because somebody numbered it, and there is no standards body behind it.

Applications are free to ignore an NCC, implement only the parts they need, propose alternatives, or demonstrate that the approach does not work. Adoption is the useful measure. If independent projects can implement the same convention and understand each other, the convention is useful. If nobody wants it, the document has no special status.

How can people contribute?

The NCC repository is open for discussion and contributions:

https://github.com/imattau/nostr-community-conventions

Contribution can take a number of forms. You can review an existing NCC and look for assumptions that only work in one application, implement one and report where the specification is unclear, point out where a proposal duplicates an existing NIP, suggest a smaller design, open an issue, submit a pull request, or improve an existing draft directly.

You can also propose a new convention for an interoperability problem you have encountered, or argue that something should not be an NCC at all. The goal is not to accumulate documents. The goal is to identify conventions that make independent Nostr software easier to connect.

A contribution does not need to be a complete specification. A concrete interoperability problem is often enough to start with. “Three applications represent the same concept differently. Could they share a convention?” is usually a better starting point than simply deciding that another numbered document is needed.

What makes a good NCC?

A useful NCC should build on existing Nostr primitives wherever possible, avoid changing relay behaviour, solve a problem that more than one application could reasonably encounter, and have clear boundaries around what it does and does not solve.

It should also be possible to ignore it without breaking ordinary Nostr behaviour. The smaller the convention can remain while still solving the interoperability problem, the better.

Where this could go

The individual NCCs become more useful when they compose. Service identity, discovery, capabilities, authority and operational state can all describe different parts of the same service, while software applications, releases, artefacts and package metadata can form a separate but compatible stack.

That creates room for applications to be built around durable Nostr identities rather than whichever server, domain or registry happens to host them at the time.

Some NCCs will change significantly as they are implemented. Some may disappear, and others may turn out to belong in existing NIPs instead. Nostr has generally developed by building things, comparing approaches and standardising what proves useful.

NCCs make that middle stage more explicit. Not everything needs to become part of the protocol, but useful conventions also do not need to remain private to individual applications.


Write a comment