butr
Get startedFrameworks

Next.js (App Router)

Client-component provider, RSC boundary, and the EVM-only bundle pattern.

butr is a client-side wallet library: it touches window, wallet extensions, and localStorage. Under the App Router that means the provider must be a client component.

The "use client" boundary

The demo-next reference is EVM-only (no @usebutr/svm or @usebutr/wallets in the bundle); see EVM-only setup for the install, chain list, and bundle rationale. This page covers only what is specific to the App Router. The provider module starts with "use client":

src/wallet-provider.tsx
"use client";

import type { WalletManagerConfig } from "@usebutr/core";
import { discoverEvmAdapters } from "@usebutr/evm";
import { WalletManagerProvider } from "@usebutr/react";
import type { ReactNode } from "react";

// EVM-only: no @usebutr/svm or @usebutr/wallets in the bundle.
const config: WalletManagerConfig = {
  sources: [discoverEvmAdapters],
  storageKeyPrefix: "butr-demo",
};

const WalletProvider = ({ children }: { children: ReactNode }) => (
  <WalletManagerProvider config={config}>{children}</WalletManagerProvider>
);

export { WalletProvider };

The config at module scope is safe on the server: creating the manager has no side effects, and the provider starts it in an effect, so discovery and storage never run during a server render.

Mount it in the root layout (a Server Component importing a Client Component is fine):

src/app/layout.tsx
import type { ReactNode } from "react";
import { WalletProvider } from "../wallet-provider";

const RootLayout = ({ children }: { children: ReactNode }) => (
  <html lang="en">
    <body>
      <WalletProvider>{children}</WalletProvider>
    </body>
  </html>
);

export default RootLayout;

Any page using butr hooks (useConnect, useWallet, …) must also be "use client".

demo-next goes one step further and renders the connected wallet on the server: it persists to cookies and passes initialState to the provider. That walkthrough is SSR without the hydration flash.

Chains

The chain registries live in @usebutr/core, which the EVM-only bundle already includes:

import { EVM_CHAINS_LIST } from "@usebutr/core";

Why this keeps Solana out of the bundle is covered in EVM-only setup.

Want multi-chain instead?

Put autoDiscovery() from @usebutr/wallets in sources, in a "use client" module, same as Vite. See Provider setup for the full pattern.

Source: apps/demo-next/src/wallet-provider.tsx in the butr repository. Run pnpm dev --filter=demo-next → https://usebutr.demo-next.localhost.