Skip to content

Post

Changing a specification is mostly a migration problem

The NIP-54 format migration shows how an implementation tool can address a reviewer's compatibility concern and make a specification change easier to adopt.

· 3 min readNostrDeveloper tools

A change to NIP-54, the Nostr wiki specification, is merged: articles are written in Djot instead of Asciidoc. I authored the specification change after the protocol’s creator had proposed the new format. When review raised the migration question, I wrote a converter and linked it from the pull request.

The useful engineering work was making the existing content compatible with the new rule.

The decision had already been taken

In October 2025, fiatjaf, who created the protocol, opened an issue titled “wikis as djot: this time is different”. The body is one line: “I’m sorry for the AsciiDoc detour.” The author of the protocol had proposed a different format in public before my contribution.

The issue was then closed without a merged specification change. A proposed format still needed both specification text and a migration path for existing articles.

The review was one question

I opened the migration PR, and Vitor Pamplona, who maintains one of the most used Nostr clients, asked about compatibility:

Has anybody coded the migration to Djot?

Not “is Djot better”. Not “do we agree”. The specification could be rewritten in an afternoon; the wiki articles that existed in the old format could not. Every one of them lives on relays, published by people who are not reading this pull request and will not rewrite anything by hand. A format change without a migration path is a proposal to break other people’s data and let them deal with it.

That question identified the compatibility work the specification text alone did not cover.

The migration tool

asciidoc-to-djot parses the Asciidoc AST with @asciidoctor/core and emits Djot through a custom converter backend, rather than trying to rewrite the text with regular expressions. That choice is most of why it works: the constructs that matter in a wiki article are structural: headings, links, and NIP-54’s wikilink syntax. NIP-54 wikilinks in particular have to become Djot reference-style links, [cryptocurrency][] rather than [[cryptocurrency]]. A regex pass handles common constructs and silently corrupts the rest.

The package exposes the converter as both a library and a CLI. I posted it on the pull request as the migration path the review had asked for.

The specification change merged three weeks later.

What the tool did and did not do

It is worth being precise, because the flattering version of this story is not the true one. The converter does not appear in the merged diff: that diff is one file, the NIP itself, 63 lines added and 37 removed. The tool changed nothing about the specification. It changed what a reviewer had to assume about the consequences of merging it.

The transferable part

When an agreed change remains unmerged, the unresolved question is often who pays its migration cost. The useful contribution is not another argument for the change; it is the tool, compatibility layer, or transition plan that keeps existing users from absorbing that cost individually.

The merged specification diff does not contain the converter. Linking the tool addressed the migration concern raised in review: the text names the new rule, while the converter gives existing content a path to it.