Integrating RainbowKit for Wallet Connection on a Website
RainbowKit is a UI library on top of wagmi for wallet connection. Provides a ready-made, polished modal dialog with support for MetaMask, WalletConnect, Coinbase Wallet, Rainbow and others. Can be set up in an hour and customized to match the project's design.
Installation
npm install @rainbow-me/rainbowkit wagmi viem @tanstack/react-query
Minimal Integration
// app/providers.tsx
'use client';
import '@rainbow-me/rainbowkit/styles.css';
import { RainbowKitProvider, getDefaultConfig } from '@rainbow-me/rainbowkit';
import { WagmiProvider } from 'wagmi';
import { mainnet, polygon, arbitrum } from 'wagmi/chains';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const config = getDefaultConfig({
appName: 'MyApp',
projectId: process.env.NEXT_PUBLIC_WC_PROJECT_ID!,
chains: [mainnet, polygon, arbitrum],
});
const queryClient = new QueryClient();
export function Providers({ children }: { children: React.ReactNode }) {
return (
<WagmiProvider config={config}>
<QueryClientProvider client={queryClient}>
<RainbowKitProvider>
{children}
</RainbowKitProvider>
</QueryClientProvider>
</WagmiProvider>
);
}
// Connection button — ready-made, with all state inside
import { ConnectButton } from '@rainbow-me/rainbowkit';
export function Header() {
return (
<header>
<Logo />
<ConnectButton />
</header>
);
}
ConnectButton shows: "Connect Wallet" button if not connected, address + balance + avatar if connected, network switch if network is not supported.
Theme Customization
import { RainbowKitProvider, darkTheme, lightTheme, midnightTheme } from '@rainbow-me/rainbowkit';
// Built-in themes with accent color
<RainbowKitProvider
theme={darkTheme({
accentColor: '#6366f1', // indigo-500
accentColorForeground: 'white',
borderRadius: 'medium',
fontStack: 'system',
overlayBlur: 'small',
})}
>
For full control — custom theme:
import { cssStringFromTheme } from '@rainbow-me/rainbowkit';
const myTheme = {
colors: {
accentColor: '#6366f1',
accentColorForeground: '#fff',
actionButtonBorder: 'rgba(255,255,255,0.04)',
actionButtonBorderMobile: 'rgba(255,255,255,0.08)',
actionButtonSecondaryBackground: 'rgba(255,255,255,0.08)',
closeButton: 'rgba(224,232,255,0.6)',
closeButtonBackground: 'rgba(255,255,255,0.08)',
connectButtonBackground: '#1c1c1e',
connectButtonBackgroundError: '#ff494a',
connectButtonInnerBackground: 'linear-gradient(0deg, rgba(255,255,255,0.075), rgba(255,255,255,0.15))',
connectButtonText: '#fff',
connectButtonTextError: '#fff',
connectionIndicator: '#30e000',
downloadBottomCardBackground: 'linear-gradient(126deg, rgba(0,0,0,0) 9.49%, rgba(120,120,120,0.2) 100%)',
downloadTopCardBackground: 'linear-gradient(126deg, rgba(120,120,120,0.2) 0%, rgba(0,0,0,0) 90.51%)',
error: '#ff494a',
generalBorder: 'rgba(255,255,255,0.08)',
generalBorderDim: 'rgba(255,255,255,0.04)',
menuItemBackground: 'rgba(255,255,255,0.08)',
modalBackdrop: 'rgba(0,0,0,0.5)',
modalBackground: '#1c1c1e',
modalBorder: 'rgba(255,255,255,0.08)',
modalText: '#fff',
modalTextDim: 'rgba(224,232,255,0.3)',
modalTextSecondary: 'rgba(255,255,255,0.6)',
profileAction: 'rgba(255,255,255,0.08)',
profileActionHover: 'rgba(255,255,255,0.16)',
profileForeground: 'rgba(255,255,255,0.05)',
selectedOptionBorder: 'rgba(224,232,255,0.1)',
standby: '#ff8c00',
},
// fonts, radii, shadows ...
};
Custom Connect Button
If the standard button doesn't fit the design — use the headless API:
import { ConnectButton } from '@rainbow-me/rainbowkit';
export function CustomConnectButton() {
return (
<ConnectButton.Custom>
{({
account,
chain,
openAccountModal,
openChainModal,
openConnectModal,
authenticationStatus,
mounted,
}) => {
const ready = mounted && authenticationStatus !== 'loading';
const connected = ready && account && chain && authenticationStatus !== 'unauthenticated';
return (
<div {...(!ready && { 'aria-hidden': true, style: { opacity: 0, pointerEvents: 'none' } })}>
{!connected ? (
<button onClick={openConnectModal} className="btn-primary">
Connect Wallet
</button>
) : chain.unsupported ? (
<button onClick={openChainModal} className="btn-danger">
Switch Network
</button>
) : (
<div className="flex gap-2">
<button onClick={openChainModal} className="btn-ghost flex items-center gap-1">
{chain.hasIcon && (
<img src={chain.iconUrl} alt={chain.name} className="h-4 w-4" />
)}
<span>{chain.name}</span>
</button>
<button onClick={openAccountModal} className="btn-ghost">
{account.displayBalance && `${account.displayBalance} · `}
{account.displayName}
</button>
</div>
)}
</div>
);
}}
</ConnectButton.Custom>
);
}
Wallet List
By default, RainbowKit shows popular wallets. For a custom set:
import {
injectedWallet,
metaMaskWallet,
rainbowWallet,
walletConnectWallet,
coinbaseWallet,
safeWallet,
} from '@rainbow-me/rainbowkit/wallets';
const config = getDefaultConfig({
wallets: [
{
groupName: 'Popular',
wallets: [metaMaskWallet, rainbowWallet, coinbaseWallet],
},
{
groupName: 'Others',
wallets: [walletConnectWallet, safeWallet, injectedWallet],
},
],
// ...
});
Timeframe: installation and basic integration with custom theme — half a day. With custom button and custom wallet list — 1 day.







