12<html lang="en">3<head>4<meta charset="utf-8">5<meta name="viewport" content="width=device-width, initial-scale=1">6<title>NIP-31 - Dealing with unknown event kinds — Nostr Instruction Manual</title>7<meta name="description" content="NIP-31 (deprecated): the alt tag, a plaintext fallback summary that lets clients display custom event kinds they do not understand.">8<link rel="preload" href="../assets/fonts/michroma-400-latin.woff2" as="font" type="font/woff2" crossorigin>9<link rel="preload" href="../assets/fonts/exo2-var-latin.woff2" as="font" type="font/woff2" crossorigin>10<link rel="preload" href="../assets/fonts/sairacondensed-600-latin.woff2" as="font" type="font/woff2" crossorigin>11<link rel="preload" href="../assets/fonts/sairacondensed-700-latin.woff2" as="font" type="font/woff2" crossorigin>12<link rel="preload" href="../assets/fonts/sairacondensed-500-latin.woff2" as="font" type="font/woff2" crossorigin>13<link rel="preload" href="../assets/fonts/sharetechmono-400-latin.woff2" as="font" type="font/woff2" crossorigin>14<link rel="preload" href="../assets/fonts/exo2-400i-latin.woff2" as="font" type="font/woff2" crossorigin>15<link rel="icon" href="../assets/favicon.svg" type="image/svg+xml">16<link rel="stylesheet" href="../assets/manual.css">17</head>18<body>1920<svg width="0" height="0" style="position:absolute">21 <defs>22 <marker id="arr" markerWidth="9" markerHeight="9" refX="7" refY="4.5" orient="auto">23 <path d="M1,1 L8,4.5 L1,8 Z" fill="#f26a00"/>24 </marker>25 <marker id="arrb" markerWidth="9" markerHeight="9" refX="7" refY="4.5" orient="auto">26 <path d="M1,1 L8,4.5 L1,8 Z" fill="#2e5f9e"/>27 </marker>28 </defs>29</svg>3031<div class="page">32 <span class="staple s1"></span><span class="staple s2"></span>3334 <header class="band">35 <a class="logo" href="../index.html">NOSTR<b>▸</b>PROTOCOL MANUAL</a>36 <span class="booklet-note">Chapter 31 - Interop</span>37 </header>38 <nav class="tabs">39 <a href="../index.html">Contents</a>40 <a href="#overview" class="on">Overview</a>41 <a href="#spec">Spec</a>42 <a href="#examples">Examples</a>43 <a href="#history">History</a>44 </nav>4546 <div class="chapter">47 <div class="nipno" data-n="31">31</div>48 <div class="titles">49 <div class="kicker">Nostr Implementation Possibility - Hex № 31</div>50 <h1>Dealing with unknown event kinds</h1>51 <p class="sub">A plaintext fallback summary, the <code>alt</code> tag, so that a client can show something useful for an event kind it does not understand.</p>52 </div>53 <div class="stamp">Deprecated</div>54 </div>5556 <main class="spread">57 <div class="main">5859 <h2 class="bar" id="overview"><span class="num">1</span> Overview</h2>6061 <div class="box danger">62 <span class="tag">Deprecated</span>63 <p>The source repository marks this NIP <span class="chip unrecommended">unrecommended</span> with the warning: <em>unnecessarily bloated</em>. The <code>alt</code> tag adds a copy of the event's meaning to every custom event. Do not add it to new event kinds. For real interoperability with unknown kinds, use the handler discovery flow in <a href="89.html">NIP-89</a> instead.</p>64 </div>6566 <p>Nostr lets any NIP claim a new event kind. A custom protocol can publish events that carry structured data, not prose. A social client that only understands <code>kind:1</code> text notes cannot render such an event. This NIP defines a fallback for that case.</p>67 <p>The fallback is the <strong><code>alt</code> tag</strong>: a short human-readable plaintext summary of what the event is about. A social client that meets an unknown kind reads the <code>alt</code> tag. It shows the summary instead of a blank or nonsensical note.</p>68 <p>Clients that only know <code>kind:1</code> are not expected to ask relays for events of other kinds. But users can still reference these custom events in their notes. Without context, such a reference renders as nonsense. The fallback text improves that situation. At minimum, it tells the user to view the custom event in another client.</p>6970 <h2 class="bar" id="spec"><span class="num">2</span> The alt Tag</h2>71 <p>When a client creates an event of a new custom kind, and that kind is part of a custom protocol, and its <code>content</code> is not meant to be read as text (unlike <code>kind:1</code>), the client should add an <code>alt</code> tag. The tag has one value: the summary string.</p>7273 <div class="crt">74 <div class="titlebar">Tag format - alt</div>75<pre>"tags": [76 [<span class="s">"alt"</span>, <span class="c"><short human-readable plaintext summary></span>],77 <span class="c">... protocol-specific tags ...</span>78]</pre>79 </div>8081 <div class="tscroll"><table class="ref">82 <caption>Tag reference</caption>83 <tr><th>Tag</th><th>Value</th><th>Rule</th></tr>84 <tr><td class="btn">alt</td><td>plaintext string</td><td>A short human-readable summary of what the event is about. Add it to custom event kinds whose <code>content</code> is not readable text. This is a should, not a must.</td></tr>85 </table></div>8687 <p>The summary must give enough context on its own. Write it for a user who knows nothing about the event kind. After reading it, the user should understand what the event is, even if the client cannot render it.</p>8889 <div class="box tech">90 <span class="tag">Tech Note</span>91 <p>Two gaps in the source text. First, it defines no behavior for a custom event that lacks an <code>alt</code> tag; each client must invent its own fallback. Second, the deprecation warning names no replacement; <a href="89.html">NIP-89</a> is only referenced as an optional improvement, not as a successor. Also note: <code>alt</code> is not a single-letter tag, so relays do not index it under the <a href="01.html">NIP-01</a> rules. You cannot query it with a filter.</p>92 </div>9394 <h2 class="bar" id="behavior"><span class="num">3</span> Client Behavior</h2>95 <p>Rendering follows one decision. If the client understands the kind, it renders the event natively. If it does not, it shows the <code>alt</code> summary as plain text. The client does not need to parse the <code>content</code> of an unknown kind.</p>9697 <figure class="diagram">98 <div class="frame">99 <svg viewBox="0 0 560 200" role="img" aria-label="Decision flow: an event arrives; a known kind renders natively; an unknown kind falls back to the alt tag summary">100 <rect class="d-actor" x="10" y="75" width="120" height="50" rx="8"/>101 <text class="d-actor-label" x="70" y="97" text-anchor="middle">Event</text>102 <text class="d-note" x="70" y="114" text-anchor="middle">kind:31337</text>103 <rect class="d-actor" x="215" y="75" width="130" height="50" rx="8"/>104 <text class="d-actor-label" x="280" y="97" text-anchor="middle">Client</text>105 <text class="d-note" x="280" y="114" text-anchor="middle">kind known?</text>106 <rect class="d-actor" x="430" y="18" width="120" height="50" rx="8"/>107 <text class="d-actor-label" x="490" y="40" text-anchor="middle">Native view</text>108 <text class="d-note" x="490" y="57" text-anchor="middle">parse content</text>109 <rect class="d-actor" x="430" y="132" width="120" height="50" rx="8"/>110 <text class="d-actor-label" x="490" y="154" text-anchor="middle">Fallback view</text>111 <text class="d-note" x="490" y="171" text-anchor="middle">show alt text</text>112 <path class="d-msg d-flow" d="M132,100 L212,100"/>113 <path class="d-msg blue" d="M347,88 C390,74 395,58 427,48"/>114 <path class="d-msg d-flow" d="M347,112 C390,126 395,142 427,152"/>115 <text class="d-label" x="388" y="52" text-anchor="middle">yes</text>116 <text class="d-label" x="388" y="152" text-anchor="middle">no</text>117 <circle r="4" fill="#f26a00">118 <animateMotion dur="2.6s" repeatCount="indefinite" path="M347,112 C390,126 395,142 427,152"/>119 </circle>120 </svg>121 </div>122 <figcaption>Fig. 31-1 — <b>Fallback decision.</b> Unknown kind? Read the <code>alt</code> tag and show the summary as plain text.</figcaption>123 </figure>124125 <div class="box hint">126 <span class="tag">Hint!</span>127 <p><code>kind:1</code>-centric clients can go one step further than plain fallback text. With <a href="89.html">NIP-89</a>, a client can discover which application handles an unknown kind and link the user straight to it.</p>128 </div>129130 <h2 class="bar" id="examples"><span class="num">4</span> Worked Example</h2>131 <p>A music application publishes an audio track as a custom <code>kind:31337</code> event. The <code>content</code> holds protocol data that only music clients parse. The <code>alt</code> tag carries the fallback summary.</p>132133 <div class="crt">134 <div class="titlebar">Custom event with alt tag - kind 31337</div>135<pre>{136 <span class="k">"id"</span>: <span class="s">"7fa31c22e0…"</span>,137 <span class="k">"pubkey"</span>: <span class="s">"9d0c44eb17…"</span>,138 <span class="k">"created_at"</span>: 1749980000,139 <span class="k">"kind"</span>: 31337,140 <span class="k">"tags"</span>: [141 [<span class="s">"d"</span>, <span class="s">"track-sunrise"</span>],142 [<span class="s">"alt"</span>, <span class="s">"An audio track: 'Sunrise'. Open this event in a music client to play it."</span>]143 ],144 <span class="k">"content"</span>: <span class="s">"{\"url\":\"https://cdn.example.com/sunrise.mp3\",\"bpm\":121}"</span>,145 <span class="k">"sig"</span>: <span class="s">"c04d19e2a5…"</span>146}</pre>147 </div>148149 <p>A user references this event in a <code>kind:1</code> note. A social client fetches the event and does not recognize <code>kind:31337</code>. It ignores the <code>content</code> and renders the <code>alt</code> summary:</p>150151 <div class="crt">152 <div class="titlebar">Social client - fallback rendering</div>153<pre><span class="c">-- timeline view --</span>154@dj_anon: check out my new track! nostr:nevent1qqs0…155 ┌──────────────────────────────────────────────────┐156 │ An audio track: 'Sunrise'. Open this event in a │157 │ music client to play it. │158 └──────────────────────────────────────────────────┘</pre>159 </div>160161 <div class="box warn">162 <span class="tag">Warning!</span>163 <p>Do not put protocol data in the <code>alt</code> tag, and do not put the fallback text in <code>content</code>. The summary is for humans only. Clients that understand the kind never read it.</p>164 </div>165166 <h2 class="bar" id="history"><span class="num">5</span> Version History</h2>167 <p>NIP-31 had a short, quiet life. It changed its mechanism once, then sat unchanged until it was marked unrecommended. Notable changes, newest first:</p>168 <ul class="patchnotes">169 <li><span class="ver">2026</span><span class="when">2026-05</span>Deprecated. fiatjaf marked the NIP <code>unrecommended</code> with the warning "unnecessarily bloated".</li>170 <li class="minor"><span class="ver">2023-25</span><span class="when">2023-2025</span>Housekeeping: author names removed from all NIP documents; cross-reference links fixed (#1740).</li>171 <li><span class="ver">2023</span><span class="when">2023-06</span>pablof7z reworked the mechanism: the fallback summary moved into a dedicated <code>alt</code> tag.</li>172 <li><span class="ver">Origin</span><span class="when">2023-05</span>fiatjaf published the first draft as "dealing with custom unknown events".</li>173 </ul>174175 <div class="credits">176 <h3 class="cardhead">Original Proposal - Credits</h3>177 <table>178 <tr><td>Author</td><td>fiatjaf</td></tr>179 <tr><td>First commit</td><td>2023-05-05 — “nip-31: dealing with custom unknown events.”</td></tr>180 <tr><td>Status</td><td>draft - unrecommended - optional — deprecated, do not implement in new kinds</td></tr>181 <tr><td>Source</td><td><a href="https://github.com/nostr-protocol/nips/blob/master/31.md">31.md on GitHub</a> - <a href="https://github.com/nostr-protocol/nips/commits/master/31.md">full change history</a></td></tr>182 </table>183 </div>184185 <h2 class="bar"><span class="num">6</span> See Also</h2>186 <ul>187 <li><a href="01.html">NIP-01</a> — the event object, kinds, and the tag rules this NIP builds on.</li>188 <li><a href="89.html">NIP-89</a> — recommended application handlers; the functional way to deal with unknown kinds.</li>189 <li><a href="10.html">NIP-10</a> — <code>kind:1</code> text notes, the format that <code>alt</code> imitates as a fallback.</li>190 </ul>191 </div>192193 <aside>194 <div class="cartridge">195 <div class="inner">196 <h3 class="cardhead">Spec Card</h3>197 <div class="lights"><span class="led err"></span><span class="led err"></span><span class="led err"></span></div>198 <dl>199 <dt>Status</dt><dd><span class="chip draft">draft</span><span class="chip unrecommended">unrecommended</span><span class="chip optional">optional</span></dd>200 <dt>Defines</dt><dd><code>alt</code> tag - plaintext fallback summary</dd>201 <dt>Kinds</dt><dd>none — applies to any custom kind</dd>202 <dt>Requires</dt><dd><a href="01.html">NIP-01</a></dd>203 <dt>Superseded by</dt><dd><a href="89.html">NIP-89</a> handler discovery</dd>204 <dt>First commit</dt><dd>2023-05-05</dd>205 <dt>Last updated</dt><dd>2026-05-31</dd>206 </dl>207 </div>208 </div>209 </aside>210 </main>211212 <nav class="navbtns">213 <a href="30.html">◀ NIP-30: Custom Emoji</a>214 <a href="32.html">NIP-32: Labeling ▶</a>215 </nav>216217 <footer class="pagefoot">218 <a href="../index.html">Nostr Protocol Manual</a>219 <span class="pageno">NIP 31 / F4</span>220 </footer>221</div>222223<script src="../assets/webmcp.js" defer></script>224</body>225</html>