> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getpara.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Para with TanStack Start

> A guide to integrate Para SDK with TanStack Start while preserving server-side rendering capabilities.

export const DemoCallout = ({variant = "card", title = "Interactive Demo", description = "Try the live demo to explore authentication flows and customize your modal before integrating."}) => {
  if (variant === "subtle") {
    return <div className="not-prose my-4 px-4 py-3 rounded-xl border border-orange-200 bg-orange-50/50">
        <div className="flex items-center justify-between gap-4">
          <p className="text-sm text-gray-700 m-0">
            {description}
          </p>
          <a href="https://demo.getpara.com/" target="_blank" rel="noopener noreferrer" className="not-prose flex-shrink-0 inline-flex items-center gap-2 px-3 py-1.5 text-xs font-semibold text-orange-600 bg-white border border-orange-200 rounded-lg hover:bg-orange-50 transition-colors no-underline">
            Try Demo
            <svg width="12" height="12" viewBox="0 0 512 512" fill="none" xmlns="http://www.w3.org/2000/svg">
              <path d="M40 472L472 40M472 40H83.2M472 40V428.8" stroke="currentColor" strokeWidth="66.6667" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
          </a>
        </div>
      </div>;
  }
  return <a href="https://demo.getpara.com/" target="_blank" rel="noopener noreferrer" className="not-prose block my-4 p-5 rounded-xl bg-gradient-to-r from-orange-600 via-pink-600 to-purple-600 hover:opacity-95 transition-opacity no-underline">
      <div className="flex items-center justify-between gap-4">
        <div>
          <h3 className="text-base font-semibold text-white m-0">{title}</h3>
          <p className="text-xs text-white/80 mt-1 m-0">{description}</p>
        </div>
        <div className="flex-shrink-0 w-8 h-8 rounded-full bg-white/20 flex items-center justify-center">
          <svg width="14" height="14" viewBox="0 0 512 512" fill="none" xmlns="http://www.w3.org/2000/svg">
            <path d="M40 472L472 40M472 40H83.2M472 40V428.8" stroke="white" strokeWidth="66.6667" strokeLinecap="round" strokeLinejoin="round" />
          </svg>
        </div>
      </div>
    </a>;
};

export const Link = ({href, label, newTab = false}) => {
  const [isHovered, setIsHovered] = useState(false);
  return <a href={href} target={newTab ? '_blank' : '_self'} rel={newTab ? 'noopener noreferrer' : undefined} className="not-prose inline-block relative text-black font-semibold cursor-pointer border-b-0 no-underline" onMouseEnter={() => setIsHovered(true)} onMouseLeave={() => setIsHovered(false)}>
      {label}
      <span className={`absolute left-0 bottom-0 w-full rounded-sm bg-gradient-to-r from-orange-600 to-purple-600 transition-all duration-300 ${isHovered ? 'h-0.5' : 'h-px'}`} />
    </a>;
};

This guide will walk you through integrating Para SDK with **TanStack Start** while preserving server-side rendering (SSR) capabilities.

<Note>
  TanStack Start is a full-stack React framework powered by TanStack Router. Para SDK uses styled-components internally which requires client-side only loading to work correctly with SSR.
</Note>

## Prerequisites

Before starting, you'll need a Para API key which you can obtain from the <Link href="https://developer.getpara.com">Para Developer Portal</Link>. You can learn to create your account and get your API key from the Developer Portal.

<Card title="Setup Developer Portal" description="Get your API key and configure your developer portal settings" imgUrl="/images/v3/developer-portal-open-graph.png" href="/v3/react/guides/customization/developer-portal-setup" horizontal />

<DemoCallout variant="subtle" />

## Installation

Install the Para React SDK and React Query:

<CodeGroup>
  ```bash npm theme={null}
  npm install @getpara/react-sdk @tanstack/react-query graz @cosmjs/cosmwasm-stargate @cosmjs/launchpad @cosmjs/proto-signing @cosmjs/stargate @cosmjs/tendermint-rpc @leapwallet/cosmos-social-login-capsule-provider long starknet wagmi@^2 viem @farcaster/mini-app-solana @farcaster/miniapp-sdk @farcaster/miniapp-wagmi-connector @solana-mobile/wallet-adapter-mobile @solana/wallet-adapter-base @solana/wallet-adapter-react @solana/wallet-adapter-walletconnect @solana/web3.js @stellar/stellar-sdk --save-exact
  ```

  ```bash yarn theme={null}
  yarn add @getpara/react-sdk @tanstack/react-query graz @cosmjs/cosmwasm-stargate @cosmjs/launchpad @cosmjs/proto-signing @cosmjs/stargate @cosmjs/tendermint-rpc @leapwallet/cosmos-social-login-capsule-provider long starknet wagmi@^2 viem @farcaster/mini-app-solana @farcaster/miniapp-sdk @farcaster/miniapp-wagmi-connector @solana-mobile/wallet-adapter-mobile @solana/wallet-adapter-base @solana/wallet-adapter-react @solana/wallet-adapter-walletconnect @solana/web3.js @stellar/stellar-sdk --exact
  ```

  ````bash pnpm theme={null}
  pnpm add @getpara/react-sdk @tanstack/react-query graz @cosmjs/cosmwasm-stargate @cosmjs/launchpad @cosmjs/proto-signing @cosmjs/stargate @cosmjs/tendermint-rpc @leapwallet/cosmos-social-login-capsule-provider long starknet wagmi@^2 viem @farcaster/mini-app-solana @farcaster/miniapp-sdk @farcaster/miniapp-wagmi-connector @solana-mobile/wallet-adapter-mobile @solana/wallet-adapter-base @solana/wallet-adapter-react @solana/wallet-adapter-walletconnect @solana/web3.js @stellar/stellar-sdk --save-exact

  ```bash bun
  bun add @getpara/react-sdk @tanstack/react-query graz @cosmjs/cosmwasm-stargate @cosmjs/launchpad @cosmjs/proto-signing @cosmjs/stargate @cosmjs/tendermint-rpc @leapwallet/cosmos-social-login-capsule-provider long starknet wagmi@^2 viem @farcaster/mini-app-solana @farcaster/miniapp-sdk @farcaster/miniapp-wagmi-connector @solana-mobile/wallet-adapter-mobile @solana/wallet-adapter-base @solana/wallet-adapter-react @solana/wallet-adapter-walletconnect @solana/web3.js @stellar/stellar-sdk --exact
  ````
</CodeGroup>

<Info>
  Using wagmi v3? See [additional dependencies](/v3/react/troubleshooting/tanstack-start#wagmi-v3-module-resolution-errors) required.
</Info>

## Setting Up Polyfills with TanStack Start

Since TanStack Start uses Vite under the hood, we need to set up polyfills for modules like crypto, buffer, etc. that Para SDK relies on. We only want to run these polyfills on the client, not on the server.

1. Install the Vite Node Polyfills plugin:

<CodeGroup>
  ```bash npm theme={null}
  npm install vite-plugin-node-polyfills --save-dev
  ```

  ```bash yarn theme={null}
  yarn add vite-plugin-node-polyfills -D
  ```

  ```bash pnpm theme={null}
  pnpm add vite-plugin-node-polyfills -D
  ```

  ```bash bun theme={null}
  bun add -d vite-plugin-node-polyfills
  ```
</CodeGroup>

2. Configure the polyfills in your `app.config.ts`:

```ts app.config.ts theme={null}
import { defineConfig } from "@tanstack/react-start/config";
import tsConfigPaths from "vite-tsconfig-paths";
import { nodePolyfills } from "vite-plugin-node-polyfills";

export default defineConfig({
  tsr: { appDirectory: "src" },

  // Base configuration (applied to both client and server)
  vite: {
    plugins: [tsConfigPaths({ projects: ["./tsconfig.json"] })],
    define: {
      // This helps modules determine the execution environment
      "process.browser": true,
    },
  },

  // Client-specific configuration
  routers: {
    client: {
      vite: {
        // Apply node polyfills only on the client side
        plugins: [nodePolyfills()],
      },
    },
  },
});
```

## Setup Postinstall Script

Add the Para setup script to your `package.json`:

```json package.json theme={null}
{
  "scripts": {
    "postinstall": "npx setup-para"
  }
}
```

## Create a Client-Only Providers Component

Create a providers component using React.lazy and ClientOnly to ensure Para SDK only loads on the client:

```tsx src/components/Providers.tsx theme={null}
import React from "react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { ClientOnly } from "@tanstack/react-router";

const queryClient = new QueryClient();

// Lazy load ParaProvider to avoid SSR issues
const LazyParaProvider = React.lazy(() =>
  import("@getpara/react-sdk").then((mod) => ({
    default: mod.ParaProvider
  }))
);

export default function Providers({ children }: React.PropsWithChildren) {
  return (
    <ClientOnly fallback={null}>
      <QueryClientProvider client={queryClient}>
        <LazyParaProvider
          paraClientConfig={{
            apiKey: import.meta.env.VITE_PARA_API_KEY || "",
          }}
          config={{
            appName: "Your App Name"
          }}
        >
          {children}
        </LazyParaProvider>
      </QueryClientProvider>
    </ClientOnly>
  );
}
```

<Note>If you're using a legacy API key (one without an environment prefix) you must provide a value to the `paraClientConfig.environment`. You can retrieve your updated API key from the Para Developer Portal at [https://developer.getpara.com/](https://developer.getpara.com/)</Note>

## Wrap Your App with Providers

Update your root component to wrap your application with the Providers component:

```tsx src/routes/__root.tsx theme={null}
import Providers from "~/components/Providers";
import { Outlet } from "@tanstack/react-router";

export function RootComponent() {
  return (
    <html>
      <head>
        <meta charSet="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
      </head>
      <body>
        <Providers>
          <main>
            <Outlet />
          </main>
        </Providers>
      </body>
    </html>
  );
}
```

<Info>
  You can learn more about the `ParaProvider` and its definition in the <Link href="/v3/react/guides/hooks/para-provider" label="ParaProvider Hooks Guide" />.
</Info>

<Note>
  The `ParaProvider` utilizes libraries like Wagmi, Graz, and Solana Wallet Adapter, to power wallet connections. Meaning you can use any of the hooks provided by these libraries when within the `ParaProvider` context. You can learn more about using external wallets in the <Link href="/v3/react/guides/external-wallets/multichain" label="External Wallets Guide" />.
</Note>

## Create a Client-Only Connect Component

Create a component that uses Para SDK hooks, ensuring it's only rendered on the client:

```tsx src/components/ParaContainer.tsx theme={null}
import { useModal, useAccount } from "@getpara/react-sdk";

export function ParaContainer() {
  const { openConnectModal, openWalletModal } = useModal();
  const account = useAccount();

  return (
    <div>
      {account.isConnected && account.embedded.wallets?.length ? (
        <div>
          <p>Connected: {account.embedded.wallets[0].address}</p>
          <button onClick={openWalletModal}>
            Manage Wallet
          </button>
        </div>
      ) : (
        <button onClick={openConnectModal}>
          Connect Wallet
        </button>
      )}
    </div>
  );
}
```

<Note>
  Learn more about the hooks used in this example:

  * <Link href="/v3/react/guides/hooks/use-modal" label="useModal" /> - Control the Para modal programmatically (openConnectModal, openWalletModal)
  * <Link href="/v3/react/guides/hooks/use-account" label="useAccount" /> - Get account connection status and wallet details
</Note>

Use it in your pages with ClientOnly wrapper:

<Warning>
  The `import "@getpara/react-sdk/styles.css"` is **required** for the Para modal to display correctly. Without this import, the modal will not be visible. You can import it in your root route or any page that uses Para components.
</Warning>

```tsx src/routes/index.tsx theme={null}
import React from "react";
import { createFileRoute, ClientOnly } from "@tanstack/react-router";
import "@getpara/react-sdk/styles.css";

// Lazy load Para container component
const LazyParaContainer = React.lazy(() =>
  import("~/components/ParaContainer").then((mod) => ({
    default: mod.ParaContainer,
  }))
);

function Home() {
  return (
    <main className="flex flex-col items-center justify-center min-h-screen gap-6 p-8">
      <h1 className="text-2xl font-bold">Para Modal Example</h1>

      <ClientOnly fallback={<p>Loading Para components...</p>}>
        <LazyParaContainer />
      </ClientOnly>
    </main>
  );
}

export const Route = createFileRoute("/")({
  component: Home,
});
```

<Accordion title="Why Client-side Only Loading?">
  The Para SDK uses styled-components internally which can cause issues during server-side rendering. By using `React.lazy` and `ClientOnly`, we ensure Para components are only evaluated in the browser environment where styled-components works correctly.
</Accordion>

## Example

<Card horizontal title="TanStack Start Example" imgUrl="/images/v3/framework-tanstack-start.png" href="https://github.com/getpara/examples-hub/tree/3.0.0/web/with-react-tanstack-start" description="See a complete TanStack Start example with Para SDK integration." />

## Next Steps

Success you've set up Para with TanStack Start! Now you can expand your application with wallet connections, account management, and more.

<CardGroup cols={3}>
  <Card title="Build with React Hooks" description="Access account data and wallet operations" imgUrl="/images/v3/general-hooks.png" href="/v3/react/guides/hooks" icon="code" />

  <Card title="Sign Messages & Transactions" description="Learn to sign messages and send transactions" imgUrl="/images/v3/general-signing.png" href="/v3/react/guides/web3-operations/sign-with-para" icon="signature" />

  <Card title="Customize Your Setup" description="Theme the modal and configure advanced options" imgUrl="/images/v3/general-customize.png" href="/v3/react/guides/customization/modal" icon="palette" />
</CardGroup>
