From ce6ade73b467dcd4b7e6c84cff2c46f3ee5fd9f2 Mon Sep 17 00:00:00 2001
From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com>
Date: Tue, 21 Jul 2026 15:53:17 -0400
Subject: [PATCH] docs: bring the Integrate page and version references up to
date
docs.html was missing everything from this session's work:
- The disconnectedCallback/crypto-worker-teardown gotcha (found via the
BitRoad integration) -- now a callout right where the element is first
mounted, since that's the step where it actually bites.
- Talking to the element directly (getPublicKey/signEvent/nip44Encrypt/
nip44Decrypt as instance methods) as an alternative to window.nostr,
with BitRoad's adapter as the worked example.
- claimSigner() failing gracefully (returns false, doesn't throw) when a
NIP-07 extension has locked window.nostr down -- was previously
undocumented entirely; this is the exact bug just fixed.
- Theming via CSS custom properties, with the full property list and
BitRoad's mapping as a real example.
Also fixed two stale "(v0.3)" references to docs/spec.md in README.md and
CONTRIBUTING.md -- the spec was bumped to v0.4 earlier this session for the
rollback-detection changes but these two mentions were missed.
Co-Authored-By: Claude Sonnet 5 That's it — the element renders its own sign-in/create/recover UI inside a shadow root, so it won't collide with your site's CSS. Prefer this if your app already holds a reference to the element — e.g. you built the sign-in UI yourself
+ instead of relying on <bitlogin-auth> from the DOM (including indirectly, by resetting an
+ ancestor's innerHTML — a common pattern in hand-rolled UI without a
+ framework's reconciler) tears down its crypto Web Worker. If that happens mid-session,
+ every signing call made afterward just hangs forever with no error, because the worker
+ is gone and nothing ever replies — a call already in flight when it happens can even
+ look like it succeeded. If your app re-renders the container this element lives in,
+ give it a container that's never replaced wholesale and toggle the hidden
+ attribute instead of removing the element. See the account manager demo's source for a
+ single-page example, or BitRoad's src/nostr/bitloginAdapter.mjs /
+ #bitloginMount (a sibling Nostr commerce app that embeds BitLogin) for a
+ worked example of keeping the element alive across a host app's own re-renders.
+ React to sign-in and sign-out
@@ -73,6 +87,23 @@ const plain = await window.nostr.nip44.decrypt(peerPubkeyHex, cipher);
and back.
Or talk to the element directly — no
+ window.nostr contention<bitlogin-auth> mirrors the same four calls as instance methods, scoped to that specific
+ element rather than the single shared window.nostr slot:
+ const bl = document.querySelector('bitlogin-auth');
+
+const pubkey = await bl.getPublicKey();
+const signed = await bl.signEvent({ kind: 1, content: 'hello', tags: [] });
+const cipher = await bl.nip44Encrypt(peerPubkeyHex, 'hi there');
+const plain = await bl.nip44Decrypt(peerPubkeyHex, cipher);window.nostr-reading app code. It keeps working even if something else
+ currently owns window.nostr (another extension, a different widget instance), and it's what a host
+ app should use if it wants a specific, known signer rather than "whichever provider is active this moment."
+ BitRoad's src/nostr/bitloginAdapter.mjs is a real example: its signer adapter calls these four
+ methods directly and never touches window.nostr at all.Supporting multiple signing methods (extensions, NIP-46, BitLogin)
window.nostr is a single global slot — only one provider can occupy it at a time. If a user also
@@ -120,6 +151,16 @@ if (window.bitlogin?.releaseSigner()) {
window.bitlogin.releaseSigner() also fire bitlogin-signer-claimed /
bitlogin-signer-released events (on the element and on window, respectively) if you'd
rather react to the change than check a return value.claimSigner() can fail without breaking anything. Some NIP-07 extensions
+ install window.nostr as a non-configurable, non-writable property specifically to stop another
+ script from overwriting it. When that happens, claimSigner() returns false instead
+ of throwing (and bitlogin-signer-claimed's event.detail carries
+ { windowNostrClaimed: false, error }), and every BitLogin sign-in flow completes normally
+ regardless — the failure only means window.nostr still points at that other extension. If your
+ app talks to the element directly (previous step) this never matters at all; only code that reads
+ window.nostr itself is affected, and only for as long as the other extension holds the slot.
+ Choose your relays
@@ -127,6 +168,33 @@ if (window.bitlogin?.releaseSigner()) {
discovery-relays at relays you trust for your users. Use at least three vault relays for
redundancy — capsule publication and reads use a quorum, so no single relay is a single point of failure.
The widget renders in a shadow root, but every color, radius, font, and its max-width are all read from CSS
+ custom properties on :host — and custom properties inherit through the shadow boundary, so your
+ page's own CSS can override every one of them without touching the widget's internals:
bitlogin-auth {
+ --bl-accent: #3d9bff; /* primary button / link / focus ring color */
+ --bl-accent-hover: #2f86e0; /* primary button hover */
+ --bl-accent-fg: #04101f; /* text color on top of --bl-accent */
+ --bl-bg: #12151f; /* card background */
+ --bl-fg: #eaeef6; /* body text */
+ --bl-muted: #98a2b6; /* secondary text */
+ --bl-border: rgba(255, 255, 255, 0.10);
+ --bl-input-bg: #1a1e2b; /* input / credential-box background */
+ --bl-danger: #ff6b6b;
+ --bl-danger-bg: rgba(255, 107, 107, 0.16);
+ --bl-radius: 14px;
+ --bl-font-family: Inter, ui-sans-serif, system-ui, sans-serif;
+ --bl-max-width: none; /* default 380px keeps it a fixed-width card;
+ override to fill a wider container */
+}
+ Overriding none of these is a valid choice — the widget falls
+ back to its own light theme, a prefers-color-scheme: dark media query, and a
+ data-theme="dark"|"light" attribute override for pages with their own theme toggle. See BitRoad's
+ bitlogin-auth { ... } rule in its src/styles.css for a real integration that maps
+ every one of these onto its own design tokens.
No account database, no password-reset email, no server-side session. The account manager demo