NIPs (Nostr Implementation Possibilities) are technical specifications that Nostr developers create to define how specific event types and tags are used. These can be written before or after the feature is implemented and often go through multiple revisions before becoming stable enough to matter. Once two or more clients fully implement the proposal, it is merged into the main repository. This process ensures that while new ideas are encouraged, they are also rigorously reviewed and tested. There are generally two paths for NIPs: 1. New Ideas, when developers just have a hunch on a new solution and want to quickly write something up to gather feedback from the community. These are my favorite NIPs because they generally introduce a new way of thinking about a problem we are all having. And because they are not just a general solution, but a specific proposal, it allows us to see the entire picture in just a few paragraphs. Even though they are my favorite, they are quite "green" and usually spur 2-3 separate solutions in following PRs by different authors. 2. Existing implementations that need to explain what they are doing. These happen when a client is already running the code in production and simply wants to explain to the rest of the community how to generate and interpret the events the client is creating. These NIPs start much more stable than the former and allow for fewer changes, but because there is already an implementation available, it's a market-tested solution that might just need a few adjustments before others start implementing it. Well-written specs ensure clarity, reduce ambiguity, and help developers implement the proposal consistently. The text should be VERY short, precise, prescriptive, and actionable by other devs. Start by introducing the new kind or tag in the first sentence and jump straight into a mockup of how the event looks like. The mockup should be self-explanatory and provide clues to what the remaining of the document will talk about. Some folks like to add long/verbose introductions, conclusions, and discussions of the reasons why the NIP is needed or why certain features are there. But those are largely unnecessary and are more appropriate to be placed in the body of the Pull Request descriptor. Start your NIP with the following template: ``` NIP-<pick a number> ====== <Title> ------------------ `draft` `optional` Event kind <new kind> defines <whatever it does>. Tags <one or two of the most important ones> <describe what they do>. As an example: ```jsonc { "kind": <your kind>, "tags": [ <your tags> ], "content": "", //... } `` ` Relays MUST... Clients MUST... ## <Details 1> ## <Details 2> ## <How to find them> ``` Your number for the NIP is irrelevant. Just pick a random number that is available so that you can fork the repo, create a file with that name, and start writing. This number will likely change once the NIP is merged. The NIPs title must be self-explanatory and short. If it helps, try to imagine which name would be best to add to the list of NIPs on the readme.md file. Same for event type names. Picture something that is short, unique and that devs can just remove the space to have a class name. The `draft` `optional` tags are there because unless you are working on NIP-01, everything is draft and everything is optional. If you want to write a mandatory NIP, you better make sure your text is so good that it can be added to `01.md` directly without overcomplicating the protocol. Start by describing the new event type, what it does and its main tags. Show the mockup and then start introducing all the other tags and how clients and relays should behave when implementing it. Use the words MUST, SHOULD, MAY, SHOULD NOT, and MUST NOT to define the mandatory behaviors of those declaring compliance with the NIP. Keep it simple. The specification should be designed to ensure that different clients, relays, and services can implement it without requiring substantial changes to their existing infrastructure. Ideally, devs should be able to implement the entire NIP from near scratch in just a few hours. Don't use jargon. Don't declare a vocabulary of words. Use simple words that anyone can understand and quickly code a demo of all the features in the NIP. They can learn about your reasons as they develop their implementation. Write expecting buggy implementations. The protocol must be resilient to varying implementations and network conditions, and gracefully handle coding errors or random gibberish. You want to promote a defensive design that anticipates misguided implementations, avoids breaking changes, and maximizes compatibility across the ecosystem. What happens if there are two tags with the same name? What happens if events that have missing tags are found? Buggy implementations will exist. The writing and reading clients are generally different and must be ready for anything that shows up on each side. Avoid abstractions, extensible and modular designs. Yes, they can be hidden underneath your text, but writing for them is a mistake and just overcomplicates things. Write for a specific use case and close all possible options to the items/features declared in the text. Make sure you are implementing those. There is no point in declaring things that are not going to be used in the short term. We can always add more in the future and we don't need a recipe on how to add more later. Label your relay hosts, setting kinds, and other data management necessities. Every NIP has a way to find out the user's preferred relay associated with the use case. Sometimes it's through a relay hint others through a separate event kind that just lists the user's home relays or contains a list of "following" events designed for the use case. Each NIP can create their own way of finding events. You cannot add new root fields. Use tags instead. Root fields are special and require changes to the core protocol everyone implements. Any new field will take years to come to reality. Once you propose an idea, try not to change too much. It will take time for other devs to wrap their minds around it. If you keep changing it, even if those changes reflect the request of the reviewers in the PR, it just confuses everyone. Sometimes things change so much that it is worth doing two PRs with separate specifications that solve the same problem. That allows devs to analyze the two propositions side by side and decide which one is better. Always add a test case or an example. This is an absolute requirement if the NIP is complex, like a new encryption scheme. But even for simpler NIPs, test cases help devs to quickly verify if their implementations meet the minimum standard for compliance. They not only add peace of mind, but they also provide some welcoming dopamine when a new dev is trying to implement your NIP. Managing state is hard. Doing it with different implementations and hosting them in separate relays is even harder. If your NIP has multiple events to manage state, like group administration actions (add/remove member, change names/icons, invite/reporting events) try to structure them in a way that devs can quickly see the state machine of all possible state changes. Specify data formats explicitly. Clearly define the format of all data fields, including type (e.g., string, integer), encoding (e.g., base64, hex), and structure (e.g., array, object). Specify constraints like length limits, valid characters, and optional/required fields. Tags are case-sensitive. Avoid having to specify new encodings, but if you do, make sure to include test cases that encompass all potential cases. It's ok to not propose the most efficient way of solving the problem. A simple but slightly less efficient design is preferred over a complex but more efficient one. We already use hex and base64 codes to represent binary bytes in JSON, which wastes 25-50% of space. That level of waste is ok if the solution becomes simpler to code. It's not about you. You may think you must convince everyone that your particular way of solving the problem is the best and get some ego points with yourself. While some of that is beneficial to the debate, be open-minded to the other possible solutions. Once merged, the NIP is not yours anymore. Anyone can change in any way they see fit. If your work is great, people will remember your name. If it just got the conversation started to become something completely different from what you proposed, they will also remember you.