Claude
Skills
Sign in
Back

ai-ui-patterns

Included with Lifetime
$97 forever

Teaches design patterns for building AI-powered React interfaces. Use when creating chatbots, intelligent assistants, streaming UIs, or any AI-driven user experience in React.

Design

What this skill does


# AI UI Patterns

## Table of Contents

- [When to Use](#when-to-use)
- [Instructions](#instructions)
- [Details](#details)
- [Source](#source)

Building AI-powered interfaces – from chatbots to intelligent assistants – requires careful integration of backend AI services with reactive UI components. In this chapter, we explore design patterns in React for such interfaces, focusing on **two implementations**: a plain React app (using Vite) and a Next.js app. We'll use **OpenAI's API** (via the Vercel AI SDK) as our AI engine, and TailwindCSS for styling. Key topics include prompt management, streaming responses, input debouncing, error handling, and how these patterns differ between Vite and Next.js. We also highlight reusable component patterns and **Vercel's AI UI components (AI Elements)** for building polished chat UIs.

## When to Use

- Use this when building conversational AI interfaces that stream responses from LLMs
- This is helpful for integrating OpenAI, Anthropic, or other AI providers into React applications
- Use this when you need patterns for prompt management, streaming, error handling, and AI-specific UI

## Instructions

- Use the Vercel AI SDK's `useChat` hook for managing conversation state and streaming responses
- Keep API keys on the server — use Next.js API routes or a separate backend for AI calls
- Enable streaming (`stream: true`) for responsive real-time output in chat interfaces
- Debounce input for autocomplete features; disable input during response streaming for chat
- Build reusable components (ChatMessage, InputBox) decoupled from data-fetching logic

## Details

> **Note:** While this article uses OpenAI as an example, the Vercel AI SDK supports multiple model providers including **Gemini**, **OpenAI**, and **Anthropic**. You can easily swap between providers through the SDK's unified interface – we're just choosing one option for demonstration purposes.

### Introduction: AI Interfaces in React

AI-driven user interfaces (UIs) have become popular with the rise of LLMs like ChatGPT. Unlike traditional UIs, AI interfaces often involve conversational interactions, dynamic content streaming, and asynchronous backend calls. This introduces unique challenges and patterns for React developers. A typical AI chat interface consists of a **frontend** (for user input and displaying responses) and a **backend** (to call the AI model). The backend is essential to keep API keys and heavy processing off the client for security and performance. Tools like Vercel's **AI SDK** make it easier to connect to providers (OpenAI, HuggingFace, etc.) and stream responses in real-time. We'll explore how to set up both a Next.js app and a Vite (React) app to handle these concerns, and discuss best practices that apply to both.

**Key patterns covered:**

- Structuring AI prompt data and managing conversation state
- Streaming AI responses to the UI for real-time feedback
- Debouncing user input to avoid spamming the API
- Error handling and fallbacks in the UX
- Reusable UI components for messages, inputs, and more (with TailwindCSS)
- Architectural differences: Next.js route handlers vs. Vite with a Node backend

By the end, you'll be equipped to build a responsive, robust AI-powered UI in React, whether you prefer Next.js or a Vite toolchain.

### Project Setup and Tools

Before diving into code, ensure you have the necessary packages and configurations:

- **React & Vite:** Initialize a Vite + React project (e.g. `npm create vite@latest my-ai-app -- --template react`). For Next.js, you can use `npx create-next-app` or the Next 13 App Router templates. Both will work – we'll highlight differences as we go.

- **TailwindCSS:** Set up Tailwind in your project for quick styling.

- **OpenAI API & Vercel AI SDK:** Install OpenAI's library or the Vercel AI SDK. We will use **Vercel's AI SDK** (`npm i ai`) which provides helpful React hooks (`useChat`, `useCompletion`) and server utilities. This SDK is framework-agnostic, working with Next.js, vanilla React, Svelte, and more. It simplifies streaming and state management, and is free/open-source.

- **API Keys:** Get your OpenAI API key from the OpenAI dashboard and store it safely. In Next.js, put it in `.env.local` (e.g. `OPENAI_API_KEY=sk-...`) and never commit it. In a Vite app, **do not** expose the key in client code – instead, use a backend proxy or environment variable on the server.

### Setting Up AI Endpoints (Next.js vs. Vite)

**Next.js Implementation:** Next.js allows us to create **route handlers** as serverless functions. We can define an API route that the React front-end will call for AI responses:

```typescript
// app/api/chat/route.ts (Next.js)
import { Configuration, OpenAIApi } from 'openai-edge';
import { OpenAIStream, StreamingTextResponse } from 'ai';

export const runtime = 'edge';

const config = new Configuration({ apiKey: process.env.OPENAI_API_KEY });
const openai = new OpenAIApi(config);

export async function POST(req: Request) {
  const { messages } = await req.json();
  const response = await openai.createChatCompletion({
    model: 'gpt-3.5-turbo',
    stream: true,
    messages: messages.map((m: any) => ({ role: m.role, content: m.content }))
  });
  const stream = OpenAIStream(response);
  return new StreamingTextResponse(stream);
}
```

In this handler, we receive a JSON body containing an array of messages (chat history). We call OpenAI's chat completion with `stream: true` to get a streaming response. We then wrap the response in a `StreamingTextResponse` provided by the AI SDK to pipe it back to the client in chunks. The Next.js API route keeps our API key on the server and streams data efficiently.

**Vite (React) Implementation:** In a Vite app, there's no built-in server, so we need to create our own backend for the OpenAI calls. This can be a simple Node/Express server:

```javascript
// backend/server.js (Node/Express for Vite app)
import express from 'express';
import { Configuration, OpenAIApi } from 'openai';

const app = express();
app.use(express.json());

const config = new Configuration({ apiKey: process.env.OPENAI_API_KEY });
const openai = new OpenAIApi(config);

app.post('/api/chat', async (req, res) => {
  try {
    const { messages = [] } = req.body;
    const systemMsg = { role: 'system', content: 'You are a helpful assistant.' };
    const inputMessages = [systemMsg, ...messages];
    const response = await openai.createChatCompletion({
      model: 'gpt-3.5-turbo',
      stream: false,
      messages: inputMessages
    });
    const content = response.data.choices[0].message?.content;
    res.json({ content });
  } catch (err) {
    console.error(err);
    res.status(500).json({ error: 'Internal Server Error' });
  }
});

app.listen(6000, () => console.log('API server listening on http://localhost:6000'));
```

During development, you can configure the Vite dev server to proxy `/api` calls to this backend (e.g. in `vite.config.js`, set `server.proxy['/api'] = 'http://localhost:6000'`). The key is that the React app calls a **relative `/api/chat` endpoint**, which the proxy/hosting will route to your server code. This keeps the OpenAI key hidden.

**Enabling Streaming in Node:** The above Express example returns the full response after completion (`stream: false` for simplicity). To stream in Node, you can use OpenAI's HTTP stream: set `stream: true` and handle the response as a stream of data. This involves reading the `response.data` stream and flushing chunks to the client with `res.write()`. If you choose to stick with full responses (no streaming), the UI patterns still largely apply – but streaming greatly improves UX.

### Prompt Handling and Conversation State

At the heart of any AI interface is **prompt management** – assembling user input (and context) into a prompt or message sequence for the AI model. In a chat scenario, we maintain a list of messages, each with a role and content. OpenAI's Chat API expects messages in t
Files: 1
Size: 18.3 KB
Complexity: 27/100
Category: Design

Related in Design