Join our Discord Community

React AI Web Preview

Live iframe preview with navigation controls. Build interactive AI-generated UIs with React, Next.js, and TypeScript, featuring URL navigation and console logging for shadcn/ui applications.

Trying to implement AI Elements?

Join our Discord community for help from other developers.


Live iframe preview with navigation controls for AI-generated UIs using React, Next.js, and TypeScript. UI generation without preview is useless. Users need to see what the AI actually built, not just trust a description. This free open source shadcn/ui component provides safe iframe embedding for your conversational AI applications using Vercel AI SDK in JavaScript frameworks.

Interactive web preview

Live iframe with navigation controls:

Loading component...

The React component provides URL navigation bar, iframe sandbox for safe preview, and optional console logging. Built with TypeScript for type safety and designed for seamless integration in your JavaScript projects.

Installation

npx shadcn@latest add https://www.shadcn.io/registry/ai.json
npx shadcn@latest add https://www.shadcn.io/registry/ai.json
pnpm dlx shadcn@latest add https://www.shadcn.io/registry/ai.json
bunx shadcn@latest add https://www.shadcn.io/registry/ai.json

Usage

import {
  WebPreview,
  WebPreviewNavigation,
  WebPreviewUrl,
  WebPreviewBody,
} from "@/components/ai/web-preview";

<WebPreview defaultUrl="https://example.com">
  <WebPreviewNavigation>
    <WebPreviewUrl />
  </WebPreviewNavigation>
  <WebPreviewBody />
</WebPreview>;

Why iframe instead of opening new tabs?

New tabs kill the workflow in React applications. Users lose context switching back and forth. Plus generated URLs are often temporary—bookmark a v0 link and it's dead in 24 hours in Next.js projects.

Embedded preview keeps everything in one place in TypeScript components. Users can test the generated interface, navigate around, and provide feedback without losing their conversation context in AI chat applications using JavaScript frameworks.

Usage with AI SDK

Generate and preview UI in real-time in React applications:

"use client";

import {
  WebPreview,
  WebPreviewNavigation,
  WebPreviewUrl,
  WebPreviewBody,
} from "@/components/ai/web-preview";
import {
  PromptInput,
  PromptInputTextarea,
  PromptInputSubmit,
} from "@/components/ai/prompt-input";
import { Loader } from "@/components/ai/loader";
import { useState } from "react";

export default function UIGenerator() {
  const [previewUrl, setPreviewUrl] = useState("");
  const [prompt, setPrompt] = useState("");
  const [isGenerating, setIsGenerating] = useState(false);

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!prompt.trim()) return;

    setIsGenerating(true);
    try {
      const response = await fetch("/api/generate-ui", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ prompt }),
      });

      const data = await response.json();
      setPreviewUrl(data.url);
      setPrompt("");
    } catch (error) {
      console.error("Generation failed:", error);
    } finally {
      setIsGenerating(false);
    }
  };

  return (
    <div className="flex flex-col h-full max-w-6xl mx-auto p-6">
      <div className="flex-1 mb-4">
        {isGenerating ? (
          <div className="flex flex-col items-center justify-center h-full">
            <Loader size={32} />
            <p className="mt-4 text-muted-foreground">Generating your UI...</p>
          </div>
        ) : previewUrl ? (
          <WebPreview defaultUrl={previewUrl} className="h-full">
            <WebPreviewNavigation>
              <WebPreviewUrl />
            </WebPreviewNavigation>
            <WebPreviewBody />
          </WebPreview>
        ) : (
          <div className="flex items-center justify-center h-full border-2 border-dashed rounded-lg">
            <p className="text-muted-foreground">
              Your generated UI will appear here
            </p>
          </div>
        )}
      </div>

      <PromptInput onSubmit={handleSubmit}>
        <PromptInputTextarea
          value={prompt}
          onChange={(e) => setPrompt(e.currentTarget.value)}
          placeholder="Describe the UI you want to create..."
          disabled={isGenerating}
        />
        <PromptInputSubmit
          status={isGenerating ? "streaming" : "ready"}
          disabled={!prompt.trim() || isGenerating}
        />
      </PromptInput>
    </div>
  );
}

Backend route for UI generation:

// app/api/generate-ui/route.ts
export async function POST(req: Request) {
  const { prompt } = await req.json();

  // Your UI generation logic here
  // This could use v0, CodeSandbox API, or custom generation

  // For demo, return a static URL
  const generatedUrl = `https://your-preview-service.com/preview/${Date.now()}`;

  return Response.json({
    url: generatedUrl,
    prompt,
  });
}

Examples

Preview with console logging

Debug generated UIs with console output:

Loading component...

Features

  • Iframe-based preview with sandbox security in React applications
  • URL navigation bar with keyboard support for TypeScript components
  • Optional console logging for debugging in JavaScript frameworks
  • Responsive container adapting to content in Next.js projects
  • Context-based state management for sub-components
  • Loading states for async content
  • Keyboard navigation (Enter to navigate)
  • Safe iframe sandboxing with controlled permissions
  • Perfect for AI-generated UIs, conversational AI interfaces, and AI chat applications
  • Free open source component built for Next.js with shadcn/ui design system and AI Elements
  • Optimized for Vercel AI SDK streaming and AI-generated interfaces

API Reference

WebPreview

Container component managing preview state.

PropTypeDefaultDescription
defaultUrlstring""Initial URL to load
onUrlChange(url: string) => void-Callback when URL changes
classNamestring-Additional CSS classes
...propsHTMLAttributes<HTMLDivElement>-Standard div attributes

WebPreviewNavigation

Navigation bar container.

PropTypeDescription
classNamestringAdditional CSS classes
...propsHTMLAttributes<HTMLDivElement>Standard div attributes

WebPreviewNavigationButton

Navigation control button with tooltip.

PropTypeDescription
tooltipstringTooltip text on hover
classNamestringAdditional CSS classes
...propsComponentProps<typeof Button>Button component props

WebPreviewUrl

URL input field with Enter key navigation.

PropTypeDescription
valuestringURL value (overrides context)
onChangeChangeEventHandlerInput change handler
onKeyDownKeyboardEventHandlerKeyboard event handler
...propsComponentProps<typeof Input>Input component props

WebPreviewBody

Iframe container for preview content.

PropTypeDescription
srcstringURL to load (overrides context)
loadingReactNodeLoading indicator overlay
classNamestringAdditional CSS classes
...propsIframeHTMLAttributes<HTMLIFrameElement>Iframe attributes

WebPreviewConsole

Collapsible console for log output.

PropTypeDescription
logsArray<{level, message, timestamp}>Console log entries
classNamestringAdditional CSS classes
...propsHTMLAttributes<HTMLDivElement>Standard div attributes

Keyboard interactions

KeyDescription
EnterNavigate to URL in input field
TabMove focus between navigation elements

Web preview gotchas that will frustrate you

CORS headers break everything: Generated URLs often block iframe embedding in React applications. X-Frame-Options: DENY kills your preview instantly. Check headers before embedding or users see blank frames in TypeScript components.

Sandbox restrictions are strict: Want to test localStorage in JavaScript implementations? Add allow-same-origin. Need forms? Add allow-forms. Too restrictive and features break, too loose and security suffers in Next.js projects.

Generated content timeouts: v0 URLs expire, CodeSandbox links die, temp hosting vanishes in React applications. Cache the actual HTML content, not just URLs, or previews become 404 graveyards.

Mobile viewport chaos: Desktop-generated UIs look broken on mobile in TypeScript frameworks. iPhone users see horizontal scrollbars everywhere. Test responsive behavior or add viewport controls.

HTTPS/HTTP mixed content: Secure sites can't load HTTP iframes in JavaScript applications. Generated content on HTTP breaks on HTTPS sites. Force HTTPS or provide fallback messaging in React projects.

Memory leaks with dynamic content: Switching between many generated previews without cleanup crashes browsers in Next.js implementations. Dispose of previous iframe content properly.

Integration with other components

WebPreview works seamlessly with PromptInput for generation requests in React applications. Use alongside Loader for generation states in Next.js projects. Combine with Tool to show generation steps. This free open source component integrates seamlessly with modern JavaScript frameworks.

Questions developers actually ask