Installation
PolygonKit integrates seamlessly with Remix. Follow these steps to get started.
Create a Remix project
Create a new Remix project:npx create-remix@latest my-polygon-app
cd my-polygon-app
When prompted, choose:
- TypeScript: Yes
- Deployment target: Choose your preference
Install PolygonKit
Install PolygonKit and its peer dependencies:npm install @sanketsaagar/polygon-kit wagmi viem @tanstack/react-query
Create a client-only provider
Create app/components/providers.tsx:app/components/providers.tsx
import { PolygonKitProvider } from '@sanketsaagar/polygon-kit';
import { ReactNode } from 'react';
export function Providers({ children }: { children: ReactNode }) {
return (
<PolygonKitProvider>
{children}
</PolygonKitProvider>
);
}
Create a client entry point
Create app/entry.client.tsx if it doesn’t exist:import { RemixBrowser } from '@remix-run/react';
import { startTransition, StrictMode } from 'react';
import { hydrateRoot } from 'react-dom/client';
startTransition(() => {
hydrateRoot(
document,
<StrictMode>
<RemixBrowser />
</StrictMode>
);
});
Update root layout
Wrap your app with the Providers component in app/root.tsx:import type { MetaFunction } from '@remix-run/node';
import {
Links,
LiveReload,
Meta,
Outlet,
Scripts,
ScrollRestoration,
} from '@remix-run/react';
import { Providers } from './components/providers';
export const meta: MetaFunction = () => {
return [
{ title: 'My Polygon App' },
{ name: 'description', content: 'Built with PolygonKit' },
];
};
export default function App() {
return (
<html lang="en">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<Meta />
<Links />
</head>
<body>
<Providers>
<Outlet />
</Providers>
<ScrollRestoration />
<Scripts />
<LiveReload />
</body>
</html>
);
}
Create your first page
Update app/routes/_index.tsx:import { ConnectWallet, usePolygonKit } from '@sanketsaagar/polygon-kit';
export default function Index() {
const { address, isConnected } = usePolygonKit();
return (
<div className="min-h-screen p-8">
<h1 className="text-4xl font-bold mb-8">My Polygon App</h1>
<ConnectWallet />
{isConnected && (
<div className="mt-4">
<p>Connected: {address}</p>
</div>
)}
</div>
);
}
Run your app
Start the development server:Visit http://localhost:3000 and connect your wallet!
Configuration
Customize PolygonKit with configuration options:
app/components/providers.tsx
import { PolygonKitProvider } from '@sanketsaagar/polygon-kit';
import { polygon, polygonAmoy } from 'wagmi/chains';
import { ReactNode } from 'react';
export function Providers({ children }: { children: ReactNode }) {
return (
<PolygonKitProvider
config={{
chains: [polygon, polygonAmoy],
projectId: process.env.WALLETCONNECT_PROJECT_ID,
appName: 'My Polygon App',
}}
>
{children}
</PolygonKitProvider>
);
}
Environment Variables
Create a .env file:
WALLETCONNECT_PROJECT_ID=your_project_id_here
For client-side variables, prefix with VITE_ in Remix:
VITE_WALLETCONNECT_PROJECT_ID=your_project_id_here
Access them in your code:
const projectId = process.env.VITE_WALLETCONNECT_PROJECT_ID;
Only variables prefixed with VITE_ are exposed to the client in Remix. Keep sensitive server-side variables without this prefix.
Server-Side Rendering (SSR)
PolygonKit components need to run on the client. Ensure wallet-related code only runs in the browser:
Method 1: Use ClientOnly Component
Create app/components/client-only.tsx:
app/components/client-only.tsx
import { useEffect, useState } from 'react';
export function ClientOnly({ children }: { children: React.ReactNode }) {
const [mounted, setMounted] = useState(false);
useEffect(() => {
setMounted(true);
}, []);
return mounted ? <>{children}</> : null;
}
Use it to wrap PolygonKit components:
import { ClientOnly } from '~/components/client-only';
import { ConnectWallet } from '@sanketsaagar/polygon-kit';
export default function Index() {
return (
<ClientOnly>
<ConnectWallet />
</ClientOnly>
);
}
Method 2: Lazy Load Components
import { lazy, Suspense } from 'react';
const WalletComponents = lazy(() => import('~/components/wallet-components'));
export default function Index() {
return (
<Suspense fallback={<div>Loading...</div>}>
<WalletComponents />
</Suspense>
);
}
Styling with Tailwind CSS
Add Tailwind CSS to your Remix app:
Install Tailwind
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
Configure Tailwind
Update tailwind.config.ts:import type { Config } from 'tailwindcss';
export default {
content: ['./app/**/*.{js,jsx,ts,tsx}'],
theme: {
extend: {},
},
plugins: [],
} satisfies Config;
Create CSS file
Create app/styles/tailwind.css:@tailwind base;
@tailwind components;
@tailwind utilities;
Import in root
Import in app/root.tsx:import styles from './styles/tailwind.css';
export const links = () => [{ rel: 'stylesheet', href: styles }];
Next Steps
Learn more about configuration options
Troubleshooting
Hydration Mismatch Errors
If you see hydration mismatch errors:
- Wrap wallet components in
ClientOnly
- Use lazy loading for components that interact with wallets
- Ensure localStorage access only happens on the client
Window is Not Defined
If you see “window is not defined” errors:
- Make sure wallet code only runs in the browser
- Use
typeof window !== 'undefined' checks
- Wrap components with
ClientOnly
Module Resolution Issues
If imports aren’t resolving:
- Check your
tsconfig.json paths configuration
- Ensure all peer dependencies are installed
- Clear the Remix cache:
rm -rf .cache