clone

tiny dependency-free nostr libraries for plain html, each under 5kb and named for an element. public domain

main
nobel / demo / index.html
index.html 4.2K
1<!doctype html>2<html lang="en">3<head>4<meta charset="utf-8">5<meta name="viewport" content="width=device-width, initial-scale=1">6<title>nobel demo</title>7<script src="relay.js"></script>8<script src="../neon/neon.js"></script>9<script src="../helium/helium.js"></script>10<script src="../argon/argon.js"></script>11<script src="../hydrogen/hydrogen.js"></script>12<script src="../xenon/xenon.js"></script>13<script src="../radon/radon.js"></script>14<style>15 :root { --ink:#1d1b16; --paper:#f4efe4; --line:#d8cfbd; --gas:#c2410c; --muted:#7a7263; }16 * { box-sizing:border-box; }17 body { margin:0; background:var(--paper); color:var(--ink); font:15px/1.5 ui-serif, Georgia, serif; }18 main { max-width:640px; margin:0 auto; padding:40px 20px 80px; }19 h1 { font:600 13px/1 ui-monospace, Menlo, monospace; letter-spacing:.12em; text-transform:uppercase; margin:0 0 4px; }20 h1 b { color:var(--gas); }21 .sub { color:var(--muted); margin:0 0 28px; font-style:italic; }22 .me { display:flex; gap:12px; align-items:center; font:13px ui-monospace, Menlo, monospace; color:var(--muted); margin-bottom:16px; }23 .me b { color:var(--ink); }24 form { display:flex; gap:8px; margin:0 0 12px; }25 input, textarea, button { font:inherit; color:inherit; background:#fffdf8; border:1px solid var(--line); border-radius:6px; padding:8px 10px; }26 textarea { flex:1; resize:vertical; min-height:44px; }27 button { cursor:pointer; font:12px ui-monospace, Menlo, monospace; text-transform:uppercase; letter-spacing:.08em; }28 button:hover { border-color:var(--gas); color:var(--gas); }29 ol { list-style:none; padding:0; margin:28px 0 0; border-top:1px solid var(--line); }30 li { padding:14px 0; border-bottom:1px solid var(--line); }31 li header { display:flex; gap:8px; align-items:baseline; font:12px ui-monospace, Menlo, monospace; color:var(--muted); }32 li header b { color:var(--ink); max-width:14ch; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }33 li header [nrn-verified]::after { content:" ✓"; color:var(--gas); }34 li p { margin:6px 0; white-space:pre-wrap; overflow-wrap:anywhere; }35 li p img { display:block; max-width:100%; border-radius:6px; margin-top:6px; }36 li a { color:var(--gas); }37 li button { padding:2px 8px; font-size:11px; }38 .tag { color:var(--gas); }39 .log { font:12px ui-monospace, Menlo, monospace; color:var(--muted); min-height:1.5em; }40</style>41</head>42<body>43<main>44 <h1><b>nobel</b> demo</h1>45 <p class="sub">xenon + helium + argon + neon + radon, in plain HTML.</p>4647 <div class="me">signed in as <b id="me" nrn-field="name">…</b> <span id="npub"></span></div>4849 <form id="profile" nxe-publish nxe-kind="0">50 <input name="name" placeholder="your name" required>51 <button>Set name</button>52 </form>5354 <form id="compose" nxe-publish>55 <textarea name="content" placeholder="say something (links, images and nostr: mentions render)" required></textarea>56 <input name="#t" placeholder="#tag" size="8">57 <button>Post</button>58 </form>59 <div class="log" id="log"></div>6061 <ol id="feed" nxe-filter='{"kinds":[1],"limit":50}'>62 <template>63 <li>64 <header>65 <b nrn-profile="{pubkey}" nrn-field="name">{npub}</b>66 <time nne-ago="{created_at}">{ago}</time>67 <span class="tag">{#t}</span>68 </header>69 <p>{content}</p>70 <button nxe-publish nxe-kind="7" nxe-content="+" nxe-tags='[["e","{id}"],["p","{pubkey}"]]'>+ like</button>71 </li>72 </template>73 </ol>74</main>75<script>76 // Profiles are kind 0 events whose content is JSON, so build it from the form.77 profile.addEventListener("nhy:config", (evt)=>{78 evt.detail.cfg.event.content = JSON.stringify({name:new FormData(profile).get("name")})79 })80 document.addEventListener("nxe:published", (evt)=>{81 let {event, results} = evt.detail.cfg82 log.textContent = `kind ${event.kind} ${event.id.slice(0, 8)}: ` + results.map((r)=>`${r.ok ? "ok" : "failed"} ${r.relay}`).join(", ")83 })84 document.addEventListener("nxe:error", (evt)=>log.textContent = String(evt.detail.error))85 // Unfilled tag placeholders read better empty.86 document.addEventListener("nhy:event", (evt)=>evt.detail.fields["#t"] ??= "")87 let who = (window.nostr ?? helium.signer).getPublicKey()88 who.then((pk)=>{89 me.setAttribute("nrn-profile", pk)90 npub.textContent = neon.encode("npub", pk).slice(0, 16) + "…"91 })92</script>93</body>94</html>