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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@lukso/up-modal

v0.19.1

Published

Connect modal for LUKSO Universal Profiles

Readme

Table of contents

What gets auto-detected

Modal automatically configures:

| App | How | | ---------------- | ------------------------------------------------------- | | UP Mobile | WalletConnect (deep link on mobile, QR code on desktop) | | UP Extension | Browser extension, detected via EIP-6963 | | EOA wallets | Other EIP-6963 wallets (MetaMask, Coinbase, etc.) |

Installation

# pnpm
pnpm add @lukso/up-modal

# npm
npm install @lukso/up-modal

# yarn
yarn add @lukso/up-modal

Also install the required peer dependencies:

npm install @wagmi/core viem

Minimal setup

Initialize modal

import { setupLuksoConnector } from '@lukso/up-modal'

const connector = await setupLuksoConnector({
  walletConnect: {
    projectId: 'YOUR_REOWN_PROJECT_ID', // get yours at https://cloud.reown.com
  },
})

Open the Sign In modal

connector.showSignInModal()

Open the Sign Up modal

connector.showSignUpModal()

API reference

setupLuksoConnector

Returns Promise<LuksoConnector>. Call once at app initialization. Example with custom options:

import { luksoTestnet } from 'viem/chains'

const connector = await setupLuksoConnector({
  theme: 'dark',
  walletConnect: {
    projectId: 'YOUR_REOWN_PROJECT_ID', // get yours at https://cloud.reown.com
  },
  chains: {
    additional: [luksoTestnet], // add LUKSO Testnet
  },
  connectors: {
    eoa: false,
  },
  onConnect: (event) => console.log('Connected:', event.detail),
  onError: (event) => console.error('Error:', event.detail),
  onClose: () => console.log('Modal closed'),
})

Config options

| Option | Type | Default | Description | | ------------------------- | ----------------------------- | ------------- | ----------------------------------------------------------------- | | theme | 'light' \| 'dark' \| 'auto' | 'light' | Modal theme | | onConnect | (e: CustomEvent) => void | — | Called on successful connection | | onError | (e: CustomEvent) => void | — | Called on connection error | | onClose | () => void | — | Called when modal is closed | | walletConnect.enabled | boolean | true | Enable WalletConnect | | walletConnect.projectId | string | LUKSO default | WalletConnect project ID | | chains.defaultChainId | number | 42 | Default chain (LUKSO mainnet) | | chains.additional | Chain[] (from viem) | [] | Extra chains alongside LUKSO mainnet (e.g. [luksoTestnet]) | | chains.skipChainSwitch | boolean | false | Skip automatic chain switch on connect | | storage.key | string | 'up-wagmi' | localStorage key prefix for wagmi state | | connectors.upMobile | boolean | true | Show UP Mobile connector button | | connectors.upExtension | boolean | true | Show UP Extension connector button | | connectors.eoa | boolean | true | Show EOA wallets divider and button | | wagmiConfig | Config (from @wagmi/core) | auto-created | Pass your own wagmi config |

LuksoConnector methods

| Method | Description | | ------------------- | ------------------------------------------------------------------------------------ | | showSignInModal() | Opens the sign-in modal (creates <connect-modal> in document.body on first call) | | showSignUpModal() | Opens the sign-up modal for creating a new Universal Profile | | closeModal() | Closes the modal | | setTheme(theme) | Updates the theme ('light' \| 'dark' \| 'auto') — works while modal is open | | destroyModal() | Closes the modal and removes the element from the DOM | | wagmiConfig | The underlying wagmi Config instance for advanced use |

Advanced

Using your own wagmi config

import { setupLuksoConnector } from '@lukso/up-modal'
import { myWagmiConfig } from './wagmi'

const connector = await setupLuksoConnector({
  wagmiConfig: myWagmiConfig,
})

Watching connection state

import { watchConnection, getConnection } from '@wagmi/core'

const { wagmiConfig } = connector

// One-time read
const connection = getConnection(wagmiConfig)

// Subscribe to changes
const stopWatching = watchConnection(wagmiConfig, {
  onChange: (connection) => {
    console.log(connection.address, connection.chainId)
  },
})

Multi-chain support

In the default auto-setup configuration (when you don't provide a custom wagmiConfig), LUKSO mainnet is always included and cannot be removed from the supported networks. Any additional chains are added alongside it via chains.additional.

The following example adds Ethereum mainnet so users can connect from either network:

import { mainnet } from 'viem/chains'
import { setupLuksoConnector } from '@lukso/up-modal'

const connector = await setupLuksoConnector({
  chains: {
    additional: [mainnet],
  },
})

Testnets are also supported, just pass them in an array. Example of adding LUKSO Testnet and Ethereum Sepolia:

import { setupLuksoConnector } from '@lukso/up-modal'
import { luksoTestnet, sepolia } from 'viem/chains'

const connector = await setupLuksoConnector({
  chains: {
    additional: [luksoTestnet, sepolia],
  },
})

If a wallet connects on a chain that is not in this list, the modal will emit an on-error event and the connection will be rejected — since wagmi has no RPC transport configured for that chain and any calls would fail.

Framework integrations

Vue 3

Full working example.

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { setupLuksoConnector, type LuksoConnector } from '@lukso/up-modal'

const connector = ref<LuksoConnector | null>(null)

onMounted(async () => {
  connector.value = await setupLuksoConnector({ theme: 'light' })
})
</script>

<template>
  <button :disabled="!connector" @click="connector?.showSignInModal()">
    Connect
  </button>
</template>

Nuxt

Plugin (plugins/lukso.client.ts):

import { setupLuksoConnector } from '@lukso/up-modal'
import type { LuksoConnector } from '@lukso/up-modal'

let connector: LuksoConnector | null = null

export default defineNuxtPlugin(async () => {
  if (process.server) return

  connector = await setupLuksoConnector({
    theme: 'light',
    onConnect: (event) => console.log('Connected:', event.detail),
  })
})

export { connector }

Component:

<template>
  <button @click="connector?.showSignInModal()">Connect Wallet</button>
</template>

<script setup lang="ts">
  import { connector } from '~/plugins/lukso.client'
</script>

React

Full working example.

import { setupLuksoConnector } from '@lukso/up-modal'
import type { LuksoConnector } from '@lukso/up-modal'
import { useEffect, useState } from 'react'

export function ConnectButton() {
  const [connector, setConnector] = useState<LuksoConnector | null>(null)

  useEffect(() => {
    setupLuksoConnector({
      theme: 'light',
      onConnect: (event) => console.log('Connected:', event.detail),
    }).then(setConnector)
  }, [])

  return (
    <button disabled={!connector} onClick={() => connector?.showSignInModal()}>
      Connect Wallet
    </button>
  )
}

Watching connection state (requires @wagmi/core):

import { watchConnection } from '@wagmi/core'

const stopWatching = watchConnection(connector.wagmiConfig, {
  onChange: (connection) => {
    console.log('Address:', connection.address)
  },
})

Svelte

Initialization (src/lib/connector.svelte.ts):

import { setupLuksoConnector } from '@lukso/up-modal'
import type { LuksoConnector } from '@lukso/up-modal'

export const connector: { current: LuksoConnector | null } = $state({
  current: null,
})

export async function initConnector() {
  connector.current = await setupLuksoConnector({
    theme: 'light',
    onConnect: (e) => console.log('Connected:', e.detail),
  })
}

Component (ConnectButton.svelte):

<script lang="ts">
  import { connector, initConnector } from '$lib/connector.svelte'

  $effect(() => {
    initConnector()
  })
</script>

<button onclick={() => connector.current?.showSignInModal()}>
  Connect Wallet
</button>

Customization

The modal supports visual customization via CSS variables. Set them on :root or any ancestor of the <connect-modal> element.

CSS Variables

| Variable | Description | Default | | ---------------------------- | -------------------------- | --------------------------------------------- | | --up-modal-font-family | Modal font family | Inter, ui-sans-serif, system-ui, sans-serif | | --up-modal-font-color | Modal text color (light) | #243542 | | --up-modal-font-dark-color | Modal text color (dark) | #f5f8fa | | --up-modal-btn-color | Button background (light) | #ffffff | | --up-modal-btn-dark-color | Button background (dark) | #243542 | | --up-modal-btn-text | Button text & icon (light) | #243542 | | --up-modal-btn-dark-text | Button text & icon (dark) | #ffffff | | --up-modal-btn-radius | Button border radius | 12px (large) / 10px (medium) | | --up-modal-border-radius | Modal border radius | 12px | | --up-modal-bg | Modal background (light) | #f8fafb | | --up-modal-dark-bg | Modal background (dark) | #121b21 |

Example with custom brand colors

<style>
  :root {
    --up-modal-font-family: 'Roboto', sans-serif;
    --up-modal-font-color: #1e3a5f;
    --up-modal-btn-color: #4285f4;
    --up-modal-btn-text: #ffffff;
    --up-modal-bg: #eff6ff;
    --up-modal-border-radius: 20px;
  }
</style>

Internationalization

The modal ships with English (en_US) translations by default. You can customize any text string or add support for other languages.

The i18n features require @lukso/core, a separate LUKSO utilities package. Install it alongside @lukso/up-modal:

npm install @lukso/core

Translation keys

| Key | Default (English) | | ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | | connect_modal_title | Let's log you in | | connect_modal_description | Log in with your Universal Profile | | connect_modal_connectors_passkey_wallet | Passkey Wallet | | connect_modal_connectors_up_mobile | Mobile Application | | connect_modal_connectors_up_browser_extension | Browser Extension | | connect_modal_or | Or | | connect_modal_or_info | Log in with a different wallet | | connect_modal_other_connectors | Connect Wallet | | connect_modal_eoa_title | Connect your Wallet | | connect_modal_installed | INSTALLED | | connect_modal_failed_to_load | Failed to load... | | connect_modal_try_again | Try again | | connect_modal_qr_code_title | Scan to log in | | connect_modal_qr_code_description | Scan the below QR code with the Universal Profile mobile app to log in | | connect_modal_close | Close modal | | connect_modal_go_back | Go back | | sign_up_modal_title | Create Universal Profile! | | sign_up_modal_description | Choose the device on which you want to create a profile. You can use either to interact with supported apps | | sign_up_modal_use_mobile | Install the Mobile Application | | sign_up_modal_install_extension | Install the Browser Extension |

Changing the locale

The modal uses the global IntlService from @lukso/core. If your app already sets up an intl service, the modal will use it automatically. Otherwise it creates a local English instance.

import { createIntlService, setIntlService } from '@lukso/core/services/intl'

// Create a service with your translations
const intl = createIntlService({
  locale: 'de-DE',
  messages: {
    connect_modal_title: 'Wir melden Sie an',
    connect_modal_description: 'Melden Sie sich mit Ihrem Universalprofil an.',
    // ... other keys
  },
})

// Set it globally — the modal picks it up automatically
setIntlService(intl)

Overriding individual strings

If you only need to change a few labels, set the global service with your full message map. Any keys you omit will fall back to the built-in English translations.

import enMessages from '@lukso/core/translations/en_US.json'

const intl = createIntlService({
  locale: 'en-US',
  messages: {
    ...enMessages,
    connect_modal_title: 'Sign in to MyApp',
    connect_modal_description: 'Connect your Universal Profile to continue',
  },
})

setIntlService(intl)

Switching locale at runtime

import { getIntlService } from '@lukso/core/services/intl'
import germanMessages from '@lukso/core/translations/de_DE.json'

const intl = getIntlService()
intl?.setLocale('de-DE', germanMessages)
// The modal re-renders automatically

License

Apache-2.0 — see LICENSE.md for details.