Skip to main content
TanStack Start’s server-side rendering (SSR) capabilities can introduce unique challenges when integrating Para SDK. This guide addresses frequent issues and offers tailored solutions to ensure a successful implementation.
Using an LLM (ChatGPT, Claude) or Coding Assistant (Cursor, Github Copilot)? Here are a few tips:
  1. Include the Para LLM-optimized context file for the most up-to-date help
  2. Check out the Example Hub Wiki for an interactive LLM using Para Examples Hub

General Troubleshooting Steps

Before diving into specific issues, try these general troubleshooting steps:
rm -rf node_modules
npm cache clean --force
npm install
npm run build

Common Issues and Solutions

Problem: Para API key environment variables not being recognized in your application.Solution: Ensure you’re using the correct prefix for environment variables in TanStack Start and accessing them properly:
  1. In your .env file:
    VITE_PARA_API_KEY=your_api_key_here
    VITE_PARA_ENVIRONMENT=BETA
    
  2. In your constants file:
    // src/constants.ts
    export const API_KEY = import.meta.env.VITE_PARA_API_KEY || "";
    export const ENVIRONMENT = import.meta.env.VITE_PARA_ENVIRONMENT || "BETA";
    
  3. When using these in your ParaProvider:
    <LazyParaProvider paraClientConfig={{ apiKey: API_KEY, env: ENVIRONMENT }}>
      {children}
    </LazyParaProvider>
    
Problem: Missing or improperly configured Node.js polyfills causing errors like crypto is not defined or similar issues.Solution: Configure the polyfills specifically for the client bundle only:
  1. Install the plugin:
    npm install --save-dev vite-plugin-node-polyfills
    
  2. Update your app.config.ts to apply polyfills only to the client bundle:
    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()],
          },
        },
      },
    });
    
Important: Do NOT configure nodePolyfills in the top-level vite plugins array, as this will apply the polyfills to the server bundle and can cause conflicts.
Problem: Browser-specific modules not being resolved correctly, leading to missing APIs or incorrect environment detection.Solution: Add the process.browser definition to help modules determine the execution environment:
// app.config.ts
export default defineConfig({
  vite: {
    define: {
      "process.browser": true,
    },
    // other configurations...
  },
  // other configurations...
});
This setting is critical for ensuring that browser-specific code paths are correctly resolved during bundling.
Problem: Errors like styled.div is not a function or Cannot read properties of undefined (reading 'div') during server rendering.Solution: Ensure Para components are only rendered on the client side by using both React.lazy for dynamic imports and ClientOnly from TanStack Router:
import React from "react";
import { ClientOnly } from "@tanstack/react-router";

// Lazy load Para component to prevent server-side evaluation
const LazyParaProvider = React.lazy(() => 
  import("@getpara/react-sdk").then((mod) => ({ 
    default: mod.ParaProvider 
  }))
);

export function Providers({ children }) {
  return (
    <ClientOnly fallback={null}>
      <QueryClientProvider client={queryClient}>
        <LazyParaProvider paraClientConfig={{ apiKey: API_KEY, env: ENVIRONMENT }}>
          {children}
        </LazyParaProvider>
      </QueryClientProvider>
    </ClientOnly>
  );
}
The combination of React.lazy and ClientOnly ensures that Para components are not only rendered on the client side but also that the modules are not evaluated on the server.
Problem: Even with ClientOnly, you’re still seeing styled-components errors during server rendering.Solution: Module-level evaluation can still happen on the server even if the component isn’t rendered. Make sure all Para imports are lazy loaded:
  1. Don’t import directly from Para SDK at the module level:
    // AVOID this at the top level:
    import { ParaModal, useModal } from "@getpara/react-sdk";
    
  2. Instead, create wrapper components for all Para components:
    // Create a component file like ParaContainer.tsx
    export function ParaContainer() {
      // Import and use Para components here
      const { openModal } = useModal();
      return (
        <>
          <button onClick={openModal}>Open Para Modal</button>
          <ParaModal appName="Your App" />
        </>
      );
    }
    
  3. Then lazy load these wrapper components:
    const LazyParaContainer = React.lazy(() => 
      import("~/components/ParaContainer").then((mod) => ({
        default: mod.ParaContainer,
      }))
    );
    
    function HomePage() {
      return (
        <ClientOnly fallback={<p>Loading...</p>}>
          <LazyParaContainer />
        </ClientOnly>
      );
    }
    
Problem: The Para modal appears transparent or without proper styling.Solution: Import Para’s CSS file in your component:
// In your main component or route file:
import "@getpara/react-sdk/styles.css";

// Then use Para components as usual
Ensure this import is included in the component that uses Para components or in a parent component that wraps them.

Best Practices for TanStack Start Integration

  1. Client-Side Only Rendering: Always use both React.lazy and ClientOnly for Para components to avoid SSR issues.
  2. Polyfill Strategy: Configure node polyfills only for the client bundle using the routers.client.vite.plugins config.
  3. Environment Awareness: Set process.browser to true to help modules determine the execution environment.
  4. Component Boundaries: Clearly define boundaries between server and client components to prevent hydration mismatches.
  5. Error Handling: Implement error boundaries to gracefully handle any runtime errors related to Para integration.
  6. Development vs Production: Use environment-specific configurations to manage different settings for development and production builds.
By following these troubleshooting steps and best practices, you should be able to resolve most common issues when integrating Para with your TanStack Start application.

Integration Support

If you’re experiencing issues that aren’t resolved by our troubleshooting resources, please contact our team for assistance. To help us resolve your issue quickly, please include the following information in your request:
  1. 1

    A detailed description of the problem you’re encountering.

  2. 2

    Any relevant error messages or logs.

  3. 3

    Steps to reproduce the issue.

  4. 4

    Details about your system or environment (e.g., device, operating system, software version).

Providing this information will enable our team to address your concerns more efficiently.
I