Integration
Vite
The whole integration for a Vite single-page app
The simplest case. A Vite SPA has no server rendering, so there is nothing to gate — import the stylesheet and render the widget.
npm install @superbridge/widgetSetup
// src/main.tsx
import "@superbridge/widget/styles.css";
import "./index.css";
import { createRoot } from "react-dom/client";
import { App } from "./App";
createRoot(document.getElementById("root")!).render(<App />);The widget's stylesheet goes above your own, so your theme variables win. See Embedding.
// src/App.tsx
import { Widget } from "@superbridge/widget";
export function App() {
return (
<main className="mx-auto max-w-lg py-24">
<Widget localDevelopmentApiKey={import.meta.env.VITE_WIDGET_DEV_KEY} />
</main>
);
}That's the whole integration.
Environment variables
Vite only exposes variables prefixed VITE_, and they're inlined at build time. Keep the dev key out of production builds by putting it in .env.development only, or by gating on Vite's own flag:
<Widget
localDevelopmentApiKey={
import.meta.env.DEV ? import.meta.env.VITE_WIDGET_DEV_KEY : undefined
}
/>If your app has its own wallet stack
The widget uses the wagmi provider you've already mounted rather than installing a second one — but only if both halves are looking at the same wagmi module instance. With a linked or duplicated install they aren't, and the widget behaves as though your provider isn't there.
Deduplicate in your Vite config:
// vite.config.ts
export default defineConfig({
resolve: {
dedupe: ["react", "react-dom", "wagmi", "viem", "@tanstack/react-query"],
},
});If the duplicate comes from your lockfile rather than resolution, pin one version with npm overrides or pnpm pnpm.overrides. See Wallets.
Tailwind
Nothing to configure. The widget ships compiled CSS, so your Tailwind build doesn't need to scan it and shouldn't try to.
Vite with SSR
If you've added your own SSR layer, the widget needs a client-only gate — the widget reads browser APIs during setup. Either use the framework you built on (TanStack Start, React Router) or gate it yourself:
function ClientOnly({ children }: { children: React.ReactNode }) {
const [mounted, setMounted] = useState(false);
useEffect(() => setMounted(true), []);
return mounted ? <>{children}</> : null;
}