upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhzrd149 <8001706+hzrd149@users.noreply.github.com>2026-03-25 11:07:23 -0500
committerGitHub <noreply@github.com>2026-03-25 11:07:23 -0500
commitf9c48b38c0e58119fb9b1cdc38a9179586826414 (patch)
tree7b9989f3106b780bf93b19546ad21c0b74b25865
parent699e7a28f4d6e2df10660184c4f8c159adf1582d (diff)
NIP-5A: Static Websites (#1538)
-rw-r--r--5A.md163
1 files changed, 163 insertions, 0 deletions
diff --git a/5A.md b/5A.md
new file mode 100644
index 0000000..7fe24b9
--- /dev/null
+++ b/5A.md
@@ -0,0 +1,163 @@
1NIP-5A
2======
3
4Pubkey Static Websites
5----------------------
6
7`draft` `optional`
8
9This nip describes a method by which static websites can be hosted under public keys using specialized host servers
10
11### Site Manifest Definition
12
13A site manifest event MUST be a replaceable or an addressable event as defined in [NIP-01](01.md). There are two types of site manifest event kinds:
14
15- **Root site**: Uses kind `15128` and MUST NOT include a `d` tag. This is a single replaceable event per pubkey and serves as the root site for the pubkey.
16- **Named sites**: Uses kind `35128` and MUST have a `d` tag containing the site identifier. These can be smaller websites under a pubkey and can be throught of as sub-domains.
17
18The event MUST include one or more `path` tags that map absolute paths to sha256 hashes. Each `path` tag MUST have the format `["path", "/absolute/path", "sha256hash"]` where:
19- The first element is the literal string `"path"`
20- The second element is an absolute path ending with a filename and extension
21- The third element is the sha256 hash of the file that will be served under this path
22
23The event MAY include `server` tags that hint at which blossom servers can be used to find the blobs associated with the hashes.
24
25The event MAY include `title` and `description` tags that provide simple site information.
26
27The event MAY include a `source` tag that links to the site's source code repository or source archive. The `source` tag MUST have the format `["source", "<url>"]`, where `<url>` is an absolute `http` or `https` URL.
28
29The site icon SHOULD be provided by setting the `/favicon.ico` path in the manifest.
30
31For example, a root site manifest:
32
33```jsonc
34{
35 "content": "",
36 "created_at": 1727373475,
37 "id": "5324d695ed7abf7cdd2a48deb881c93b7f4e43de702989bbfb55a1b97b35a3de",
38 "kind": 15128,
39 "pubkey": "266815e0c9210dfa324c6cba3573b14bee49da4209a9456f9484e5106cd408a5",
40 "sig": "f4e4a9e785f70e9fcaa855d769438fea10781e84cd889e3fcb823774f83d094cf2c05d5a3ac4aebc1227a4ebc3d56867286c15a6df92d55045658bb428fd5fb5",
41 "tags": [
42 // path mappings: absolute path -> sha256 hash
43 ["path", "/index.html", "186ea5fd14e88fd1ac49351759e7ab906fa94892002b60bf7f5a428f28ca1c99"],
44 ["path", "/about.html", "a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456"],
45 ["path", "/favicon.ico", "fedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321"],
46 // optional: blossom server hints
47 ["server", "https://blossom.example.com"],
48 // optional: site metadata
49 ["title", "My Nostr Site"],
50 ["description", "A static website hosted on Nostr"],
51 // optional: source code location
52 ["source", "https://github.com/example/my-nostr-site"]
53 ]
54}
55```
56
57And a named site manifest:
58
59```jsonc
60{
61 "content": "",
62 "created_at": 1727373475,
63 "id": "a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456",
64 "kind": 35128,
65 "pubkey": "266815e0c9210dfa324c6cba3573b14bee49da4209a9456f9484e5106cd408a5",
66 "sig": "f4e4a9e785f70e9fcaa855d769438fea10781e84cd889e3fcb823774f83d094cf2c05d5a3ac4aebc1227a4ebc3d56867286c15a6df92d55045658bb428fd5fb5",
67 "tags": [
68 // site identifier
69 ["d", "blog"],
70 // path mappings: absolute path -> sha256 hash
71 ["path", "/index.html", "186ea5fd14e88fd1ac49351759e7ab906fa94892002b60bf7f5a428f28ca1c99"],
72 ["path", "/post.html", "a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456"],
73 // optional: blossom server hints
74 ["server", "https://blossom.example.com"],
75 // optional: site metadata
76 ["title", "My Blog"],
77 ["description", "A blog hosted on Nostr"],
78 // optional: source code location
79 ["source", "https://github.com/example/my-nostr-blog"]
80 ]
81}
82```
83
84### Host server implementation
85
86A host server is a HTTP server that is responsible for serving pubkey static websites
87
88#### Resolving Pubkeys
89
90For interoperability, host servers SHOULD use the following canonical URL formats:
91
92- Root site: `<npub>.nsite-host.com`
93- Named site: `<pubkeyB36><dTag>.nsite-host.com`
94
95`pubkeyB36` is the author's raw 32-byte pubkey encoded with base36 (lowercase, digits `0-9` then letters `a-z`, no padding) and is always exactly 50 characters.
96
97`dTag` is the site identifier (`d` tag value) as plain text. It is appended directly after `pubkeyB36` with no separator.
98
99For canonical named-site URLs, `dTag` MUST match `^[a-z0-9-]{1,13}$` and MUST NOT end with `-`.
100
101Because DNS labels are limited to 63 characters and `pubkeyB36` uses 50 of them, `dTag` MUST be 1-13 characters.
102
103This single-label format avoids wildcard certificate limitations with multi-level subdomains.
104
105If the host server is using subdomain routing it MAY serve anything at its own root domain `nsite-host.com` (a landing page for example).
106
107Example subdomains:
108- Root site: `npub10phxfsms72rhafrklqdyhempujs9h67nye0p67qe424dyvcx0dkqgvap0e.nsite-host.com`
109- Named site: `<50-char-pubkeyB36><dTag>.nsite-host.com`
110
111#### Resolving Paths
112
113When the host server receives a request and is able to determine the pubkey and identifier, it should fetch the users `10002` [NIP-65](https://github.com/nostr-protocol/nips/blob/master/65.md) relay list and lookup the site manifest event for the pubkey and identifier.
114
115For canonical subdomain formats, the host server MUST parse the left-most DNS label as follows:
116
1171. If the label is a valid `npub`, decode it and query for the root site manifest.
1182. Otherwise, if the label matches `^[0-9a-z]{50}[a-z0-9-]{1,13}$` and does not end with `-`, treat it as a named-site label where:
119 - `pubkeyB36` is the first 50 characters
120 - `dTag` is the remaining 1-13 characters
121 - decode `pubkeyB36` to a 32-byte pubkey
122 - use `dTag` as the identifier (`d` tag value)
123
124If parsing fails, the host server MUST treat the site as not found.
125
126The host server should query for the site manifest event:
127
128```jsonc
129// For root site (kind 15128, no d tag)
130{ "kinds": [15128], "authors": [<pubkey>] }
131
132// For named site (kind 35128, with d tag)
133{ "kinds": [35128], "authors": [<pubkey>], "#d": [<identifier>] }
134```
135
136Once the site manifest event is found, the host server MUST extract the path-to-hash mappings from the `path` tags in the manifest. The host server should look for a `path` tag where the second element matches the requested path.
137
138If the request path does not end with a filename the host server MUST fallback to using the `index.html` filename
139
140For example: `/` -> `/index.html` or `/blog/` -> `/blog/index.html`
141
142#### Resolving Files
143
144Once the host server has found the site manifest event and located the matching `path` tag for the requested path, it should use the sha256 hash defined in the third element of the `path` tag to retrieve the file.
145
146The host server SHOULD prioritize using `server` tags from the site manifest event as hints for which blossom servers to query. If the manifest includes `server` tags, the host server SHOULD attempt to retrieve the file from those servers first.
147
148If the pubkey has a `10063` [BUD-03 user servers](https://github.com/hzrd149/blossom/blob/master/buds/03.md) event the server MUST attempt to retrieve the file from the listed servers using the path defined in [BUD-01](https://github.com/hzrd149/blossom/blob/master/buds/01.md#get-sha256---get-blob)
149If a pubkey does not have a `10063` event and no `server` tags are found in the manifest, the host server MUST respond with a status code 404
150
151The host server MUST forward the `Content-Type`, and `Content-Length` headers from the Blossom server. If none are defined the host server MAY set `Content-Type` from the file extension in the requested path
152
153#### Handling Not Found
154
155If a host server is unable to find a site manifest event or a matching `path` tag for the requested path, it MUST use `/404.html` as a fallback path
156
157### Legacy Support
158
159Kind `34128` is marked as legacy/deprecated. This kind was used for individual static file events where each file was represented by a separate event with a `d` tag for the path and an `x` tag for the sha256 hash.
160
161Host servers MAY still support kind `34128` for backward compatibility with existing sites, but new sites SHOULD use kind `15128` (root site manifest) or kind `35128` (named site manifest) instead.
162
163Read the [legacy version](https://github.com/hzrd149/nips/blob/41e77b45a1e8a8d170097e363f7d7254797cc5c5/nsite.md) for more details.