site

personal website, served at mordaunt.dev/site
Log | Files | Refs

index.html (14255B)


      1 <!DOCTYPE html>
      2 <html lang="en">
      3 
      4 <head>
      5   <title>
      6   Hugo and nip-05 · Jack Mordaunt
      7 </title>
      8   <meta charset="utf-8">
      9 <meta name="viewport" content="width=device-width, initial-scale=1.0">
     10 <meta name="color-scheme" content="light dark">
     11 
     12 
     13 
     14 
     15 <meta name="author" content="Jack Mordaunt">
     16 <meta name="description" content="Setup nostr nip-05 with a Hugo site.">
     17 <meta name="keywords" content="blog,developer,personal,software,robust,performance,sovereign">
     18 
     19 
     20 
     21   <meta name="twitter:card" content="summary">
     22   <meta name="twitter:title" content="Hugo and nip-05">
     23   <meta name="twitter:description" content="Setup nostr nip-05 with a Hugo site.">
     24 
     25 <meta property="og:url" content="http://jackmordaunt.com/posts/hugo-nip-05/">
     26   <meta property="og:site_name" content="Jack Mordaunt">
     27   <meta property="og:title" content="Hugo and nip-05">
     28   <meta property="og:description" content="Setup nostr nip-05 with a Hugo site.">
     29   <meta property="og:locale" content="en">
     30   <meta property="og:type" content="article">
     31     <meta property="article:section" content="posts">
     32     <meta property="article:published_time" content="2025-07-16T14:57:56-03:00">
     33     <meta property="article:modified_time" content="2025-07-16T14:57:56-03:00">
     34     <meta property="article:tag" content="Hugo">
     35     <meta property="article:tag" content="Nostr">
     36 
     37 
     38 
     39 
     40 <link rel="canonical" href="http://jackmordaunt.com/posts/hugo-nip-05/">
     41 
     42 
     43 <link rel="preload" href="/fonts/fa-brands-400.woff2" as="font" type="font/woff2" crossorigin>
     44 <link rel="preload" href="/fonts/fa-regular-400.woff2" as="font" type="font/woff2" crossorigin>
     45 <link rel="preload" href="/fonts/fa-solid-900.woff2" as="font" type="font/woff2" crossorigin>
     46 
     47 
     48   
     49   
     50   <link rel="stylesheet" href="/css/coder.min.6445a802b9389c9660e1b07b724dcf5718b1065ed2d71b4eeaf981cc7cc5fc46.css" integrity="sha256-ZEWoArk4nJZg4bB7ck3PVxixBl7S1xtO6vmBzHzF/EY=" crossorigin="anonymous" media="screen" />
     51 
     52 
     53 
     54 
     55 
     56 
     57   
     58     
     59     
     60     <link rel="stylesheet" href="/css/coder-dark.min.a00e6364bacbc8266ad1cc81230774a1397198f8cfb7bcba29b7d6fcb54ce57f.css" integrity="sha256-oA5jZLrLyCZq0cyBIwd0oTlxmPjPt7y6KbfW/LVM5X8=" crossorigin="anonymous" media="screen" />
     61   
     62 
     63 
     64 
     65  
     66   
     67     
     68     <link rel="stylesheet" href="/css/custom.min.931a9d02d6f7655cd0cd50317fac1204e00c54ffd0232085acc957b2db5e1283.css" integrity="sha256-kxqdAtb3ZVzQzVAxf6wSBOAMVP/QIyCFrMlXstteEoM=" crossorigin="anonymous" media="screen" />
     69   
     70 
     71 
     72 
     73 
     74 
     75 <link rel="icon" type="image/svg+xml" href="/images/self-tiny-white.svg" sizes="any">
     76 <link rel="icon" type="image/png" href="/images/self-tiny-white.png" sizes="32x32">
     77 <link rel="icon" type="image/png" href="/images/self-tiny-white.png" sizes="16x16">
     78 
     79 <link rel="apple-touch-icon" href="/images/apple-touch-icon.png">
     80 <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon.png">
     81 
     82 <link rel="manifest" href="/site.webmanifest">
     83 <link rel="mask-icon" href="/images/safari-pinned-tab.svg" color="#5bbad5">
     84 
     85 
     86 
     87 
     88 
     89 
     90 
     91 <script defer data-domain="jackmordaunt.com" src="https://plausible.io/js/script.js"></script>
     92 
     93 
     94 
     95 
     96 </head>
     97 
     98 
     99 
    100 
    101 
    102 
    103 <body class="preload-transitions colorscheme-auto">
    104   
    105 <div class="float-container">
    106     <a id="dark-mode-toggle" class="colorscheme-toggle">
    107         <i class="fa-solid fa-adjust fa-fw" aria-hidden="true"></i>
    108     </a>
    109 </div>
    110 
    111 
    112   <main class="wrapper">
    113     <nav class="navigation">
    114   <section class="container">
    115     
    116     <a class="navigation-title" href="http://jackmordaunt.com/">
    117       Jack Mordaunt
    118     </a>
    119     
    120     
    121       <input type="checkbox" id="menu-toggle" />
    122       <label class="menu-button float-right" for="menu-toggle">
    123         <i class="fa-solid fa-bars fa-fw" aria-hidden="true"></i>
    124       </label>
    125       <ul class="navigation-list">
    126         
    127           
    128             <li class="navigation-item">
    129               <a class="navigation-link " href="/posts/">Blog</a>
    130             </li>
    131           
    132             <li class="navigation-item">
    133               <a class="navigation-link " href="/about/">About</a>
    134             </li>
    135           
    136             <li class="navigation-item">
    137               <a class="navigation-link " href="/projects/">Projects</a>
    138             </li>
    139           
    140             <li class="navigation-item">
    141               <a class="navigation-link " href="/contact/">Contact</a>
    142             </li>
    143           
    144             <li class="navigation-item">
    145               <a class="navigation-link " href="/pay-with-bitcoin/">Pay</a>
    146             </li>
    147           
    148         
    149         
    150       </ul>
    151     
    152   </section>
    153 </nav>
    154 
    155 
    156     <div class="content">
    157       
    158   <section class="container post">
    159     <article>
    160       <header>
    161         <div class="post-title">
    162           <h1 class="title">
    163             <a class="title-link" href="http://jackmordaunt.com/posts/hugo-nip-05/">
    164               Hugo and nip-05
    165             </a>
    166           </h1>
    167         </div>
    168         <div class="post-meta">
    169           <div class="date">
    170             <span class="posted-on">
    171               <i class="fa-solid fa-calendar" aria-hidden="true"></i>
    172               <time datetime="2025-07-16T14:57:56-03:00">
    173                 July 16, 2025
    174               </time>
    175             </span>
    176             <span class="reading-time">
    177               <i class="fa-solid fa-clock" aria-hidden="true"></i>
    178               2-minute read
    179             </span>
    180           </div>
    181           <div class="authors">
    182   <i class="fa-solid fa-user" aria-hidden="true"></i>
    183     <a href="/authors/jack-mordaunt/">Jack Mordaunt</a></div>
    184 
    185           <div class="categories">
    186   <i class="fa-solid fa-folder" aria-hidden="true"></i>
    187     <a href="/categories/development/">Development</a></div>
    188 
    189           <div class="tags">
    190   <i class="fa-solid fa-tag" aria-hidden="true"></i>
    191     <span class="tag">
    192       <a href="/tags/hugo/">Hugo</a>
    193     </span>
    194       <span class="separator">•</span>
    195     <span class="tag">
    196       <a href="/tags/nostr/">Nostr</a>
    197     </span></div>
    198 
    199         </div>
    200       </header>
    201 
    202       <div class="post-content">
    203         
    204         <p><a href="https://nostr.how/en/guides/get-verified"  class="external-link" target="_blank" rel="noopener">nip-05</a> is a convenience for identifying users on nostr such as <code>mordaunt@jackmordaunt.com</code>, which is
    205 shorter and more memorable than a <span class="tooltip">
    206   raw npub
    207   <span class="tooltiptext">npub14l0387z0ejfmnn3j38nnalg5p57952d84aqakqguhzx7p7pns2vqg3x78w</span>
    208 </span>
    209 .</p>
    210 <p>It works by making a <code>GET</code> request at <code>jackmordaunt.com/.well-known/nostr.json</code> and extracting the
    211 public keys from the JSON response.</p>
    212 <p>This quick guide will show you how to host your own with a Hugo site.</p>
    213 <h3 id="add-your-configuration">
    214   Add your configuration.
    215   <a class="heading-link" href="#add-your-configuration">
    216     <i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"></i>
    217     <span class="sr-only">Link to heading</span>
    218   </a>
    219 </h3>
    220 <p>Inside your <code>hugo.toml</code>, add:</p>
    221 <div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-toml" data-lang="toml"><span style="display:flex;"><span>[[params.nostr]]
    222 </span></span><span style="display:flex;"><span>  name = <span style="color:#a5d6ff">&#34;name&#34;</span>
    223 </span></span><span style="display:flex;"><span>  npub = <span style="color:#a5d6ff">&#34;npub...&#34;</span>
    224 </span></span></code></pre></div><p>If you have multiple names you want to host you can add them.</p>
    225 <div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-toml" data-lang="toml"><span style="display:flex;"><span>[[params.nostr]]
    226 </span></span><span style="display:flex;"><span>  name = <span style="color:#a5d6ff">&#34;name1&#34;</span>
    227 </span></span><span style="display:flex;"><span>  npub = <span style="color:#a5d6ff">&#34;npub...&#34;</span>
    228 </span></span><span style="display:flex;"><span>[[params.nostr]]
    229 </span></span><span style="display:flex;"><span>  name = <span style="color:#a5d6ff">&#34;name2&#34;</span>
    230 </span></span><span style="display:flex;"><span>  npub = <span style="color:#a5d6ff">&#34;npub...&#34;</span>
    231 </span></span><span style="display:flex;"><span>[[params.nostr]]
    232 </span></span><span style="display:flex;"><span>  name = <span style="color:#a5d6ff">&#34;name3&#34;</span>
    233 </span></span><span style="display:flex;"><span>  npub = <span style="color:#a5d6ff">&#34;npub...&#34;</span>
    234 </span></span></code></pre></div><p>I&rsquo;ve picked <code>nostr</code> as the subkey, but you can structure this config however you like.</p>
    235 <h3 id="define-the-output-type">
    236   Define the output type.
    237   <a class="heading-link" href="#define-the-output-type">
    238     <i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"></i>
    239     <span class="sr-only">Link to heading</span>
    240   </a>
    241 </h3>
    242 <div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-toml" data-lang="toml"><span style="display:flex;"><span>[outputFormats.nostrjson]
    243 </span></span><span style="display:flex;"><span>  mediaType = <span style="color:#a5d6ff">&#34;application/json&#34;</span>
    244 </span></span><span style="display:flex;"><span>  baseName = <span style="color:#a5d6ff">&#34;nostr&#34;</span>
    245 </span></span><span style="display:flex;"><span>  path = <span style="color:#a5d6ff">&#34;.well-known&#34;</span>
    246 </span></span><span style="display:flex;"><span>  isPlainText = <span style="color:#79c0ff">true</span>
    247 </span></span><span style="display:flex;"><span>  permalinkable = <span style="color:#79c0ff">true</span>
    248 </span></span><span style="display:flex;"><span>  notAlternative = <span style="color:#79c0ff">true</span>
    249 </span></span><span style="display:flex;"><span>
    250 </span></span><span style="display:flex;"><span>[outputs]
    251 </span></span><span style="display:flex;"><span>  home = [<span style="color:#a5d6ff">&#34;HTML&#34;</span>, <span style="color:#a5d6ff">&#34;nostrjson&#34;</span>]
    252 </span></span></code></pre></div><p>This output type tells Hugo that we want to render a JSON file.
    253 <code>nostrjson</code> is just the name of this type, you can pick whatever name you like.</p>
    254 <p>Read more about output formats <a href="https://gohugo.io/configuration/output-formats"  class="external-link" target="_blank" rel="noopener">here</a>.</p>
    255 <h3 id="add-the-json-template">
    256   Add the JSON template
    257   <a class="heading-link" href="#add-the-json-template">
    258     <i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"></i>
    259     <span class="sr-only">Link to heading</span>
    260   </a>
    261 </h3>
    262 <div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-html" data-lang="html"><span style="display:flex;"><span>{{ $nostr := .Site.Params.nostr }}
    263 </span></span><span style="display:flex;"><span>{
    264 </span></span><span style="display:flex;"><span>    &#34;names&#34;: {
    265 </span></span><span style="display:flex;"><span>      {{- range $k, $v := $nostr }}
    266 </span></span><span style="display:flex;"><span>        &#34;{{ $v.name }}&#34;: &#34;{{ printf &#34;%x&#34; $v.npub }}&#34;{{ if not (eq $k (sub ($nostr | len) 1)) }},{{ end }}
    267 </span></span><span style="display:flex;"><span>      {{- end }}
    268 </span></span><span style="display:flex;"><span>    }
    269 </span></span><span style="display:flex;"><span>}
    270 </span></span></code></pre></div><p>This template iterates all nostr configurations under <code>.Site.Params.nostr</code> and renders a key-value entry
    271 in the JSON object. The npub is hex encoded because that is the expected format.</p>
    272 <p>The complex conditional at the end is simply for placing the commas correctly.</p>
    273 <h3 id="build-it">
    274   Build it
    275   <a class="heading-link" href="#build-it">
    276     <i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"></i>
    277     <span class="sr-only">Link to heading</span>
    278   </a>
    279 </h3>
    280 <p><code>hugo build</code> and verify that the root of the output under <code>public</code> contains <code>.well-known/nostr.json</code> with
    281 the correct content!</p>
    282 <p>When you publish the site you should be able to get the JSON from doing a <code>GET</code> for <code>.well-known/nostr.json</code>.</p>
    283 <p>Lastly, you can specify relays that you are likely to be found on. You&rsquo;ll have to adjust the template.</p>
    284 <div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-html" data-lang="html"><span style="display:flex;"><span>
    285 </span></span><span style="display:flex;"><span>{
    286 </span></span><span style="display:flex;"><span>  &#34;names&#34;: {
    287 </span></span><span style="display:flex;"><span>    &#34;YOUR_NOSTR_NAME&#34;: &#34;YOUR_NOSTR_PUBLIC_KEY_IN_HEX_FORMAT&#34;
    288 </span></span><span style="display:flex;"><span>  },
    289 </span></span><span style="display:flex;"><span>  &#34;relays&#34;: {
    290 </span></span><span style="display:flex;"><span>    &#34;YOUR_NOSTR_PUBLIC_KEY_IN_HEX_FORMAT&#34;: [
    291 </span></span><span style="display:flex;"><span>      &#34;wss://relay.one&#34;,
    292 </span></span><span style="display:flex;"><span>      &#34;wss://relay.two&#34;,
    293 </span></span><span style="display:flex;"><span>      ...
    294 </span></span><span style="display:flex;"><span>    ]
    295 </span></span><span style="display:flex;"><span>  }
    296 </span></span><span style="display:flex;"><span>}
    297 </span></span></code></pre></div>
    298       </div>
    299 
    300 
    301       <footer>
    302         
    303 
    304 
    305         
    306         
    307         
    308         
    309         
    310         
    311         
    312       </footer>
    313     </article>
    314 
    315     
    316   </section>
    317 
    318     </div>
    319 
    320     <footer class="footer">
    321   <section class="container">
    322     ©
    323     
    324     2025
    325      Jack Mordaunt 
    326     ·
    327     
    328     Powered by <a href="https://gohugo.io/" target="_blank" rel="noopener">Hugo</a> & <a href="https://github.com/luizdepra/hugo-coder/" target="_blank" rel="noopener">Coder</a>.
    329     
    330   </section>
    331 </footer>
    332 
    333   </main>
    334 
    335   
    336 
    337   
    338   
    339   <script src="/js/coder.min.6ae284be93d2d19dad1f02b0039508d9aab3180a12a06dcc71b0b0ef7825a317.js" integrity="sha256-auKEvpPS0Z2tHwKwA5UI2aqzGAoSoG3McbCw73gloxc="></script>
    340   
    341 
    342   
    343 
    344   
    345 
    346 
    347   
    348 
    349   
    350 
    351   
    352 
    353   
    354 
    355   
    356 
    357   
    358 
    359   
    360 
    361   
    362 
    363   
    364 
    365   
    366 
    367   
    368 
    369   
    370 
    371   
    372 
    373   
    374 
    375   
    376 
    377   
    378 
    379   
    380 </body>
    381 </html>