Getting Started
The @lukso/up-modal package provides a connect modal for LUKSO Universal Profiles. It offers a responsive connection dialog with support for desktop and mobile, automatically detecting UP Mobile (via WalletConnect), UP Browser Extension (via EIP-6963), and other EOA wallets. Modal works with apps that use Wagmi, a library to interact Ethereum. Wagmi handles the underlying connection management, so you can use its APIs alongside the modal.


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();
Framework Integrations
- Vue 3
- Nuxt
- React
- Svelte
Full working example.
connector.ts (singleton, initialize once):
import { setupLuksoConnector, type LuksoConnector } from '@lukso/up-modal';
export const connectorPromise: Promise<LuksoConnector> = setupLuksoConnector({
theme: 'light',
});
App.vue:
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';
import { getConnection, disconnect } from '@wagmi/core';
import { connectorPromise } from './connector';
const address = ref<string | null>(null);
const connector = ref<Awaited<typeof connectorPromise> | null>(null);
const ready = ref(false);
let unwatch: (() => void) | null = null;
onMounted(async () => {
connector.value = await connectorPromise;
const { wagmiConfig } = connector.value;
function syncAddress() {
const conn = getConnection(wagmiConfig);
address.value = conn?.isConnected ? (conn.address ?? null) : null;
}
syncAddress();
ready.value = true;
unwatch = wagmiConfig.subscribe((s) => s.status, syncAddress);
});
onUnmounted(() => unwatch?.());
function openModal() {
connector.value?.showSignInModal();
}
async function handleDisconnect() {
await disconnect(connector.value!.wagmiConfig);
address.value = null;
}
</script>
<template>
<div v-if="ready && address">
<p>Connected: {{ address }}</p>
<button @click="handleDisconnect">Disconnect</button>
</div>
<button v-else-if="ready" @click="openModal">Connect</button>
</template>
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>
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);
},
});
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>