Skip to main content

Compatibility

The Wallet Kit widget requires React 18+ and is available for web applications using the JavaScript SDK.

Use Cases

  • Add a complete login UI to your React app without building custom components
  • Support multiple authentication methods (email OTP, OAuth, external wallets) from a single widget

Getting Started

Installation

npm install magic-sdk @magic-ext/wallet-kit

Usage

Initialize Magic with the WalletKitExtension, then render the MagicWidget component in your app.
JavaScript
import { Magic } from 'magic-sdk';
import { MagicWidget, WalletKitExtension } from '@magic-ext/wallet-kit';

const magic = new Magic('YOUR_API_KEY', {
  extensions: [new WalletKitExtension()],
});

export default function LoginPage() {
  const handleSuccess = (result) => {
    switch (result.method) {
      case 'email':
        // result.didToken for backend verification
        console.log('Email login:', result.didToken);
        break;
      case 'oauth':
        // result.magic.idToken for backend verification
        console.log('OAuth login:', result.magic.idToken);
        break;
      case 'wallet':
        // result.walletAddress for wallet connections
        console.log('Wallet connected:', result.walletAddress);
        break;
    }
  };

  return (
    <MagicWidget
      wallets={['metamask', 'coinbase', 'walletconnect']}
      onSuccess={handleSuccess}
      onError={(error) => console.error(error)}
    />
  );
}

Configuration

The widget displays login options based on two sources: Dashboard-configured options — Email OTP and OAuth providers (Google, Apple, GitHub, etc.) are configured in your Magic Dashboard. Enable the authentication methods you want, and they will automatically appear in the widget. Code-configured options — External wallets (MetaMask, Coinbase, etc.) are configured via the wallets prop. Only the wallets you specify will be displayed. For example, if you enable Email and Google OAuth in your dashboard and pass wallets={['metamask']}, the widget will show all three options: email input, Google sign-in button, and MetaMask.

WalletConnect

If you include 'walletconnect' in the wallets prop, the widget uses Reown (formerly WalletConnect) under the hood. A default project ID is included for development, but for production apps you should provide your own to avoid rate limiting:
JavaScript
const magic = new Magic('YOUR_API_KEY', {
  extensions: [new WalletKitExtension({ projectId: 'YOUR_REOWN_PROJECT_ID' })],
});
You can get a project ID by creating a free account at dashboard.walletconnect.com.

API Reference

Props

PropTypeDefaultDescription
displayMode'inline' | 'modal''inline'How the widget is displayed. 'inline' renders in document flow, 'modal' shows as an overlay.
isOpenbooleantrueWhether the widget is visible.
onClose() => voidCalled when the user closes the widget.
closeOnSuccessbooleanfalseAutomatically close after successful login (shows success screen for 2 seconds first).
closeOnClickOutsidebooleanfalseClose when clicking the backdrop. Only applies in modal mode.
walletsArray[]External wallets to display: 'metamask', 'coinbase', 'phantom', 'rabby', 'walletconnect'.
onSuccess(result: LoginResult) => voidCalled on successful login. See Login Results for result structure.
onError(error: Error) => voidCalled when login fails.
onReady() => voidCalled when the widget has initialized and applied theme settings.

Login Results

The onSuccess callback receives a result object with a method property indicating the authentication type:
// Email OTP login
{ method: 'email', didToken: string }

// OAuth login (Google, Apple, etc.)
{ method: 'oauth', oauth: { provider, scope, userHandle, userInfo }, magic: { idToken, userMetadata } }

// External wallet login
{ method: 'wallet', walletAddress: string }
For email logins, use result.didToken for backend verification. For OAuth logins, use result.magic.idToken.

Examples

Use modal mode to display the widget as an overlay:
JavaScript
import { useState } from 'react';
import { MagicWidget } from '@magic-ext/wallet-kit';

function App() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <>
      <button onClick={() => setIsOpen(true)}>Log in</button>
      <MagicWidget
        displayMode="modal"
        isOpen={isOpen}
        onClose={() => setIsOpen(false)}
        closeOnClickOutside
        closeOnSuccess
        onSuccess={(result) => console.log(result)}
      />
    </>
  );
}

Loading State

The widget fetches configuration from your Magic dashboard before rendering. During this time, it returns null. To show a loading indicator, render the widget with isOpen={false} and wait for onReady:
JavaScript
import { useState } from 'react';
import { Magic } from 'magic-sdk';
import { MagicWidget, WalletKitExtension } from '@magic-ext/wallet-kit';

// Create Magic instance once, outside the component
const magic = new Magic('YOUR_API_KEY', {
  extensions: [new WalletKitExtension()],
});

function LoginPage() {
  const [isLoading, setIsLoading] = useState(true);
  const [isOpen, setIsOpen] = useState(false);

  const handleReady = () => {
    setIsLoading(false);
    setIsOpen(true);
  };

  return (
    <>
      {isLoading && <div>Loading...</div>}
      <MagicWidget
        isOpen={isOpen}
        onReady={handleReady}
        onSuccess={(result) => console.log(result)}
      />
    </>
  );
}
Create the Magic instance outside your component or use useMemo to prevent recreating it on every render.

Theming

The widget automatically applies your Magic dashboard theme settings including colors and light/dark mode. Configure these in your Magic Dashboard.

Resources