Should We Be Able to "Like" Profiles on Nostr?
Technically, the Nostr protocol doesn’t stop you from sending a reaction (kind: 7) to a user’s metadata event (kind: 0). Relays will happily accept and forward it. Yet almost no Nostr clients have a heart button on profile pages.
Here is why that happens under the hood—and how we can actually fix it.
The Problem: Profiles Are Replaceable Events
In Nostr, a regular text note (kind: 1) is immutable. Once published, its event id never changes, so reactions pointing to that id stay attached to it.
User profiles (kind: 0) work differently. Under NIP-01, kind: 0 is a replaceable event. Every time you update your bio, change your profile picture, or tweak your NIP-05 handle, your client generates a brand-new kind: 0 event with a brand-new id. Relays actively discard the old one.
If a client naively attached likes to a profile’s event id (using a standard e tag), all of your profile likes would break and become orphaned the moment you edited your bio.
The Solution: Using a Tags for Replaceable Events
We don’t need to invent a new protocol rule or ask relays to do heavy database cleanup to solve this. Nostr already has a built-in mechanism for referencing replaceable events: the a tag.
While addressable events (like kind: 30023 articles) use ["a", "<kind>:<pubkey>:<d-tag>"], normal replaceable events like kind: 0 only ever have one active version per user. That means we don’t even need a d-tag—we just leave the identifier at the end empty:
["a", "0:<target-pubkey>:"]
When someone likes a profile, the client publishes a kind: 7 reaction formatted like this:
{
"kind": 7,
"content": "+",
"tags": [
["a", "0:<target-pubkey>:"],
["e", "<current-kind-0-event-id>"],
["p", "<target-pubkey>"],
["k", "0"]
]
}
• Why keep the a tag? Clients can query #a: [“0:
• Why keep the e tag? Following NIP-25, keeping the e tag records the exact version of the profile the user was looking at when they hit like, preserving historical context without breaking the aggregate count.
• Relay compatibility: Because relays automatically index all single-letter tags, this works on existing relays today with zero relay-side changes.
What Do You Think?
I’m considering adding native profile likes using this exact a tag pattern to my client.
Before I ship it, I want to hear from you: Should I add this feature to my client? Would you use a “like” button on profiles, or do profile zaps, follow lists, and badges already cover this use case for you?
Let me know your thoughts below! 👇
Write a comment