Skip to content

Commit feb0cff

Browse files
beacon: integrate xlogin for extension-free sign-in
Drop in the xlogin widget (CDN, pinned @0.0.15) — a universal Nostr/Solid login that provides a working window.nostr with no browser extension (guest key / paste / extension). /link is now button-driven (Sign in to continue -> xlogin -> resolve -> publish alsoKnownAs), no jarring auto-modal. Topbar sign-in link removed (xlogin's own button is the sign-in).
1 parent e99c8cf commit feb0cff

1 file changed

Lines changed: 24 additions & 20 deletions

File tree

public/index.html

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,6 @@
114114
<a class="tb-brand" href="/"><span class="dot"></span> nostr.social</a>
115115
<nav class="tb-nav">
116116
<a href="/link">Link your pod</a>
117-
<a href="https://jss.live/sso/?resolver=https://nostr.social" target="_blank" rel="noopener">Sign in</a>
118117
</nav>
119118
</header>
120119
<main>
@@ -128,6 +127,8 @@ <h1>A directory of <em style="font-style:italic">did:nostr</em> identities</h1>
128127
<footer>powered by <a href="https://github.com/JavaScriptSolidServer/beacon">beacon</a> · each profile resolves at <code>/.well-known/did/nostr/&lt;pubkey&gt;.json</code></footer>
129128
</main>
130129

130+
<!-- xlogin: universal Nostr/Solid login widget — extension-free (guest key / paste / extension) -->
131+
<script src="https://unpkg.com/xlogin@0.0.15"></script>
131132
<script type="module">
132133
const $ = (s) => document.querySelector(s);
133134
const view = $('#view');
@@ -254,36 +255,39 @@ <h2>${esc(c.name || short(pk))}</h2>
254255
<div id="linkstatus" class="link-status"></div>
255256
</div>`;
256257

257-
async function linkView() {
258+
function panelLink(inner) {
259+
view.innerHTML = `<div class="detail"><div class="back" id="back">← all identities</div><div class="panel link-panel">${inner}</div></div>`;
260+
$('#back').onclick = () => navigate('/');
261+
}
262+
263+
function linkView() {
258264
if ($('#q')) $('#q').value = '';
259265
$('#stat').innerHTML = '';
260-
const panel = (inner) => { view.innerHTML = `<div class="detail"><div class="back" id="back">← all identities</div><div class="panel link-panel">${inner}</div></div>`; $('#back').onclick = () => navigate('/'); };
266+
panelLink(`<h2>Link your pod</h2>
267+
<p>Linking your nostr key to a Solid pod lets <strong>did:nostr</strong> resolve to your WebID — so one-click sign-in works. No browser extension needed.</p>
268+
<div class="link-form" style="margin-top:1.1rem"><button id="link-start" class="cta">Sign in to continue</button><div id="linkstatus" class="link-status"></div></div>`);
269+
const b = $('#link-start'); if (b) b.onclick = startLink;
270+
}
261271

262-
view.innerHTML = '<div class="loading">checking your signer…</div>';
263-
if (!window.nostr) {
264-
panel(`<h2>Link your pod</h2>
265-
<p>Linking your nostr key to a Solid pod lets <strong>did:nostr</strong> resolve to your WebID — so one-click <em>Sign in with did:nostr</em> works.</p>
266-
<p>First you need a NIP-07 signer extension:</p>
267-
<div class="chips" style="margin-top:.8rem">
268-
<a class="chip" href="https://github.com/JavaScriptSolidServer/podkey" target="_blank" rel="noopener">Podkey ↗</a>
269-
<a class="chip" href="https://github.com/melvincarvalho/xlogin" target="_blank" rel="noopener">xlogin ↗</a>
270-
</div>`);
271-
return;
272-
}
272+
async function startLink() {
273+
const status = $('#linkstatus');
274+
const say = (m, k = '') => { if (status) { status.textContent = m; status.className = 'link-status' + (k ? ' ' + k : ''); } };
275+
if (!window.nostr) return say('Login widget still loading — try again in a moment.', 'err');
276+
say('Opening sign-in…');
273277
let pubkey;
274278
try { pubkey = (await window.nostr.getPublicKey()).toLowerCase(); }
275-
catch { panel('<h2>Link your pod</h2><p>Your signer declined to share your public key. Reload and try again.</p>'); return; }
276-
279+
catch { return say('Sign-in cancelled — click to try again.', 'err'); }
280+
say('Resolving your did:nostr…');
277281
const doc = await fetch(`/api/did/${pubkey}`).then((r) => r.json()).catch(() => null);
278282
const aka = (doc?.alsoKnownAs || []).find((x) => /^https?:\/\//.test(x));
279283
if (aka) {
280-
panel(`<h2>You're linked ✓</h2>
284+
panelLink(`<h2>You're linked ✓</h2>
281285
<p><code>did:nostr:${short(pubkey)}</code> resolves to your WebID:</p>
282286
<div class="didline"><span>${esc(aka)}</span></div>
283-
<p style="margin-top:1.1rem">Test it: <a href="https://jss.live/sso/?resolver=https://nostr.social" target="_blank" rel="noopener" style="color:var(--accent);font-weight:600">Sign in with did:nostr →</a></p>
284-
<details style="margin-top:1.2rem"><summary style="cursor:pointer;color:var(--muted)">Change linked pod</summary>${linkForm(aka)}</details>`);
287+
<p style="margin-top:1rem;color:var(--muted)">Apps can now resolve you to your pod.</p>
288+
<details style="margin-top:1.1rem"><summary style="cursor:pointer;color:var(--muted)">Change linked pod</summary>${linkForm(aka)}</details>`);
285289
} else {
286-
panel(`<h2>Link your pod</h2>
290+
panelLink(`<h2>Link your pod</h2>
287291
<p><code>did:nostr:${short(pubkey)}</code> isn't linked to a Solid pod yet. Enter your WebID (your pod's profile URL) and we'll publish an <code>alsoKnownAs</code> to your nostr profile (kind&nbsp;0), signed by your key.</p>
288292
${linkForm('')}`);
289293
}

0 commit comments

Comments
 (0)