npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@konemono/nostr-login

v1.7.67

Published

Nostr-Login ===========

Readme

Nostr-Login

This library is a powerful window.nostr provider.

<script src='https://www.unpkg.com/nostr-login@latest/dist/unpkg.js'></script>

Just add the above script to your HTML and get a nice UI for users to login with Nostr Connect (nip46), with an extension, read-only login, account switching, OAuth-like sign up, etc. Your app just talks to the window.nostr, the rest is handled by nostr-login.

See it in action on nostr.band.

Options

You can set these attributes to the script tag to customize the behavior:

  • data-dark-mode - true/false, default will use the browser's color theme
  • data-bunkers - the comma-separated list of domain names of Nostr Connect (nip46) providers for sign up, i.e. nsec.app,highlighter.com
  • data-perms - the comma-separated list of permissions requested by the app over Nostr Connect, i.e. sign_event:1,nip04_encrypt
  • data-theme - color themes, one of default, ocean, lemonade, purple
  • data-no-banner - if true, do not show the nostr-login banner, will need to launch the modals using event dispatch, see below
  • data-methods - comma-separated list of allowed auth methods, method names: connect, extension, readOnly, local, all allowed by default.
  • data-otp-request-url - URL for requesting OTP code
  • data-otp-reply-url - URL for replying with OTP code
  • data-title - title for the welcome screen
  • data-description - description for the welcome screen
  • data-start-screen - screen shown by default (banner click, window.nostr.* call), options: welcome, welcome-login, welcome-signup, signup, local-signup, login, otp, connect, login-bunker-url, login-read-only, connection-string, switch-account, import
  • data-signup-relays - comma-separated list of relays where nip65 event will be published on local signup
  • data-outbox-relays - comma-separated list of relays that will be added to nip65 event on local signup
  • data-signup-nstart - "true" to use start.njump.me instead of local signup
  • data-follow-npubs - comma-separated list of npubs to follow if njump.me signup is used

Example:

<script src='https://www.unpkg.com/nostr-login@latest/dist/unpkg.js' data-perms="sign_event:1,sign_event:0" data-theme="ocean"></script>

Updating the UI

Whenever user performs an auth-related action using nostr-login, a nlAuth event will be dispatched on the document, which you can listen to in order to update your UI (show user profile, etc):

document.addEventListener('nlAuth', (e) => {
  // type is login, signup or logout
  if (e.detail.type === 'login' || e.detail.type === 'signup') {
    onLogin();  // get pubkey with window.nostr and show user profile
  } else {
    onLogout()  // clear local user data, hide profile info 
  }
})

Launching, logout, etc

The nostr-login auth modals will be automatically launched whenever you make a call to window.nostr if user isn't authed yet. However, you can also launch the auth flow by dispatching a custom nlLaunch event:

document.dispatchEvent(new CustomEvent('nlLaunch', { detail: 'welcome' }));

The detail event payload can be empty, or can be one of welcome, signup, login, login-bunker-url, login-read-only, switch-account.

To trigger logout in the nostr-login, you can dispatch a nlLogout event:

document.dispatchEvent(new Event("nlLogout"));

To change dark mode in the nostr-login, you can dispatch a nlDarkMode event, with detail as darkMode boolean:

document.dispatchEvent(new CustomEvent("nlDarkMode", { detail: true }));

Use as a package

Install nostr-login package with npm and then:

import { init as initNostrLogin } from "nostr-login"

// make sure this is called before any
// window.nostr calls are made
initNostrLogin({/*options*/})

Now the window.nostr will be initialized and on your first call to it the auth flow will be launched if user isn't authed yet.

You can also launch the auth flow yourself:

import { launch as launchNostrLoginDialog } from "nostr-login"

// make sure init() was called 

// on your signup button click
function onSignupClick() {
  // launch signup screen
  launchNostrLoginDialog({
    startScreen: 'signup'
  })
}

Next.js Fix for Server Side Rendering (SSR)

nostr-login calls document which is unavailable for server-side rendering. You will have build errors. To fix this, you can import nostr-login on the client side in your component with a useEffect like this:

  useEffect(() => {
    import('nostr-login')
      .then(async ({ init }) => {
        init({
          // options
        })
      })
      .catch((error) => console.log('Failed to load nostr-login', error));
  }, []);

Note: even if your component has "use client" in the first line, this fix still may be necessary.


API:

  • init(opts) - set mapping of window.nostr to nostr-login
  • launch(startScreen) - launch nostr-login UI
  • logout() - drop the current nip46 connection

Options:

  • theme - same as data-theme above
  • startScreen - same as startScreen for nlLaunch event above
  • bunkers - same as data-bunkers above
  • devOverrideBunkerOrigin - for testing, overrides the bunker origin for local setup
  • onAuth: (npub: string, options: NostrLoginAuthOptions) - a callback to provide instead of listening to nlAuth event
  • perms - same as data-perms above
  • darkMode - same as data-dark-mode above
  • noBanner - same as data-no-banner above
  • isSignInWithExtension - true to bring the Sign in with exception button into main list of options, false to hide to the Advanced, default will behave as true if extension is detected.

OTP login

If you supply both data-otp-request-url and data-otp-reply-url then "Login with DM" button will appear on the welcome screen.

When user enters their nip05 or npub, a GET request is made to <data-otp-request-url>[?&]pubkey=<user-pubkey>. Server should send a DM with one-time code to that pubkey and should return 200.

After user enters the code, a GET request is made to <data-otp-reply-url>[?&]pubkey=<user-pubkey>&code=<code>. Server should check that code matches the pubkey and hasn't expired, and should return 200 status and an optional payload. Nostr-login will deliver the payload as otpData field in nlAuth event, and will save the payload in localstore and will deliver it again as nlAuth on page reload.

The reply payload may be used to supply the session token. If token is sent by the server as a cookie then payload might be empty, otherwise the payload should be used by the app to extract the token and use it in future API calls to the server.

Examples

TODO

  • fetch bunker list using NIP-89
  • Amber support
  • allow use without the UIs
  • add timeout handling
  • more at issues