Fixing SWR Rate Limiting in v0 Preview Environment

The Problem

When using SWR (or any data fetching hooks) in v0’s preview environment, you may encounter “Too Many Requests” errors. This happens because v0’s Next Lite runtime environment (may) overlap layouts, triggers, etc making real API calls in a non-standard way that can quickly hit rate limits.

The Solution

Detect when your app is running in v0’s preview environment and disable SWR calls (as needed - maybe just for troublshooting, etc.), returning mock data instead.

Step 1: Create a V0 Environment Context

Since process.env.VERCEL_URL can only be accessed on the server, create a context to pass this information to client components:

// lib/contexts/v0-environment-context.tsx
"use client"

import { createContext, useContext } from "react"

const V0EnvironmentContext = createContext<boolean>(false)

export function V0EnvironmentProvider({
  children,
  isV0Environment,
}: {
  children: React.ReactNode
  isV0Environment: boolean
}) {
  return (
    <V0EnvironmentContext.Provider value={isV0Environment}>
      {children}
    </V0EnvironmentContext.Provider>
  )
}

export function useV0Environment() {
  return useContext(V0EnvironmentContext)
}

Step 2: Add Provider to Root Layout

In your root app/layout.tsx (server component), check the URL and pass it down:

// app/layout.tsx
import { V0EnvironmentProvider } from "@/lib/contexts/v0-environment-context"

export default function RootLayout({ children }: { children: React.ReactNode }) {
  // Check if running in v0 preview environment
  const isV0Environment =
    process.env.VERCEL_URL?.includes("vusercontent.net") ?? false

  return (
    <html>
      <body>
        <V0EnvironmentProvider isV0Environment={isV0Environment}>
          {children}
        </V0EnvironmentProvider>
      </body>
    </html>
  )
}

Step 3: Update Your SWR Hooks

Modify your SWR hooks to check the environment and return mock data in v0:

// hooks/use-your-data.ts
"use client"

import useSWR from "swr"
import { useV0Environment } from "@/lib/contexts/v0-environment-context"

export function useYourData() {
  const isV0Environment = useV0Environment()

  // In v0 environment, return mock data without making API calls
  const { data, error, isLoading, mutate } = useSWR(
    isV0Environment ? null : "/api/your-endpoint", // null key disables SWR
    fetcher,
    {
      revalidateOnFocus: false,
      revalidateOnReconnect: false,
    }
  )

  // Return mock data in v0 environment
  if (isV0Environment) {
    return {
      data: { /* your mock data */ },
      error: null,
      isLoading: false,
      mutate: async () => {},
    }
  }

  return { data, error, isLoading, mutate }
}

Why This Works

  1. Server-side detection: VERCEL_URL is checked in a server component where it’s accessible
  2. Client-side usage: The flag is passed down via React Context to client components
  3. SWR disabled: Passing null as the SWR key prevents any API calls
  4. Mock data: Your UI continues to work with placeholder data in v0 preview

Key Points

  • :white_check_mark: Use VERCEL_URL.includes("vusercontent.net") to detect v0 environment
  • :white_check_mark: Check in server component, pass down via context
  • :white_check_mark: Return null as SWR key to disable fetching
  • :white_check_mark: Provide mock data so your UI still renders
  • :cross_mark: Don’t use NEXT_PUBLIC_V0_ENV (shared between prod and v0)
  • :cross_mark: Don’t check process.env.VERCEL_URL on the client (will error)

Result

Your app will work perfectly in both v0 preview and production, without hitting rate limits or making unnecessary API calls during development in v0.

1 Like

Thanks so much for sharing this! I’ve added the handbook tag so it’s easily accessible for others in the community.

Appreciate the contribution!

1 Like