site

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

hugo-nip-05.md (2801B)


      1 +++ 
      2 draft = false
      3 date = 2025-07-16T14:57:56-03:00
      4 title = "Hugo and nip-05"
      5 description = "Setup nostr nip-05 with a Hugo site."
      6 slug = ""
      7 authors = ["Jack Mordaunt"]
      8 tags = ["hugo", "nostr"]
      9 categories = ["development"]
     10 externalLink = ""
     11 series = []
     12 +++
     13 
     14 [nip-05](https://nostr.how/en/guides/get-verified) is a convenience for identifying users on nostr such as `mordaunt@jackmordaunt.com`, which is 
     15 shorter and more memorable than a {{< tooltip tip="npub14l0387z0ejfmnn3j38nnalg5p57952d84aqakqguhzx7p7pns2vqg3x78w" >}}raw npub{{< /tooltip >}}.
     16 
     17 It works by making a `GET` request at `jackmordaunt.com/.well-known/nostr.json` and extracting the
     18 public keys from the JSON response.
     19 
     20 This quick guide will show you how to host your own with a Hugo site.
     21 
     22 ### Add your configuration.
     23 
     24 Inside your `hugo.toml`, add:
     25 
     26 ```toml
     27 [[params.nostr]]
     28   name = "name"
     29   npub = "npub..."
     30 ```
     31 
     32 If you have multiple names you want to host you can add them.
     33 
     34 ```toml
     35 [[params.nostr]]
     36   name = "name1"
     37   npub = "npub..."
     38 [[params.nostr]]
     39   name = "name2"
     40   npub = "npub..."
     41 [[params.nostr]]
     42   name = "name3"
     43   npub = "npub..."
     44 ```
     45 
     46 I've picked `nostr` as the subkey, but you can structure this config however you like.
     47 
     48 ### Define the output type.
     49 
     50 ```toml
     51 [outputFormats.nostrjson]
     52   mediaType = "application/json"
     53   baseName = "nostr"
     54   path = ".well-known"
     55   isPlainText = true
     56   permalinkable = true
     57   notAlternative = true
     58 
     59 [outputs]
     60   home = ["HTML", "nostrjson"]
     61 ```
     62 
     63 This output type tells Hugo that we want to render a JSON file.
     64 `nostrjson` is just the name of this type, you can pick whatever name you like.
     65 
     66 Read more about output formats [here](https://gohugo.io/configuration/output-formats).
     67 
     68 ### Add the JSON template
     69 
     70 ```html
     71 {{ $nostr := .Site.Params.nostr }}
     72 {
     73     "names": {
     74       {{- range $k, $v := $nostr }}
     75         "{{ $v.name }}": "{{ printf "%x" $v.npub }}"{{ if not (eq $k (sub ($nostr | len) 1)) }},{{ end }}
     76       {{- end }}
     77     }
     78 }
     79 ```
     80 
     81 This template iterates all nostr configurations under `.Site.Params.nostr` and renders a key-value entry
     82 in the JSON object. The npub is hex encoded because that is the expected format.
     83 
     84 The complex conditional at the end is simply for placing the commas correctly.
     85 
     86 ### Build it
     87 
     88 `hugo build` and verify that the root of the output under `public` contains `.well-known/nostr.json` with
     89 the correct content!
     90 
     91 When you publish the site you should be able to get the JSON from doing a `GET` for `.well-known/nostr.json`.
     92 
     93 Lastly, you can specify relays that you are likely to be found on. You'll have to adjust the template.
     94 
     95 ```html
     96 
     97 {
     98   "names": {
     99     "YOUR_NOSTR_NAME": "YOUR_NOSTR_PUBLIC_KEY_IN_HEX_FORMAT"
    100   },
    101   "relays": {
    102     "YOUR_NOSTR_PUBLIC_KEY_IN_HEX_FORMAT": [
    103       "wss://relay.one",
    104       "wss://relay.two",
    105       ...
    106     ]
    107   }
    108 }
    109 ```