Plain
$ pnpm build
> next build

   ▲ Next.js 16.0.0
   Creating an optimized production build ...
 ✓ Compiled successfully in 4.2s
 ✓ Generating static pages (12/12)

Route (app)                Size  First Load JS
┌ ○ /                    1.9 kB         112 kB
├ ○ /_not-found           993 B         103 kB
└ ƒ /api/chat             141 B         102 kB
Wrap
TypeError: Cannot read properties of undefined (reading 'map')
    at MessageList (components/message-list.tsx:18:22)
    at renderWithHooks (react-dom.development.js:16305:18)
    at mountIndeterminateComponent (react-dom.development.js:20069:13)
Line Numbers
import { streamText } from "ai"
export async function POST(request: Request) {  const { messages } = await request.json()
  const result = streamText({    model: "anthropic/claude-sonnet-4.5",    messages,  })
  return result.toUIMessageStreamResponse()}
Header
Terminal
$ pnpm add ai @ai-sdk/react zod
Progress: resolved 412, reused 398, downloaded 14, added 14, done
dependencies:
+ @ai-sdk/react 3.0.12
+ ai 6.0.12
+ zod 4.1.12
Done in 2.8s using pnpm v10.18.0
Actions
app/api/chat/route.ts
import { streamText } from "ai"
export async function POST(request: Request) {  const { messages } = await request.json()
  const result = streamText({    model: "anthropic/claude-sonnet-4.5",    messages,  })
  return result.toUIMessageStreamResponse()}
Destructive
Error
TypeError: Cannot read properties of undefined (reading 'map')
    at MessageList (components/message-list.tsx:18:22)
    at renderWithHooks (react-dom.development.js:16305:18)
    at mountIndeterminateComponent (react-dom.development.js:20069:13)
Diff
components/greeting.tsx
export function Greeting({ name }: Props) {  return <p>Hello, {name}</p>  return <p className="text-sm">Hello, {name}!</p>}
Highlighted Lines
import { streamText } from "ai"
export async function POST(request: Request) {  const { messages } = await request.json()
  const result = streamText({    model: "anthropic/claude-sonnet-4.5",    messages,  })
  return result.toUIMessageStreamResponse()}
Height
Logs
[01] GET /api/chat 200 in 12ms
[02] GET /api/chat 200 in 19ms
[03] GET /api/chat 200 in 26ms
[04] GET /api/chat 200 in 33ms
[05] GET /api/chat 200 in 40ms
[06] GET /api/chat 200 in 47ms
[07] GET /api/chat 200 in 14ms
[08] GET /api/chat 200 in 21ms
[09] GET /api/chat 200 in 28ms
[10] GET /api/chat 200 in 35ms
[11] GET /api/chat 200 in 42ms
[12] GET /api/chat 200 in 49ms
[13] GET /api/chat 200 in 16ms
[14] GET /api/chat 200 in 23ms
[15] GET /api/chat 200 in 30ms
[16] GET /api/chat 200 in 37ms
[17] GET /api/chat 200 in 44ms
[18] GET /api/chat 200 in 51ms
[19] GET /api/chat 200 in 18ms
[20] GET /api/chat 200 in 25ms
[21] GET /api/chat 200 in 32ms
[22] GET /api/chat 200 in 39ms
[23] GET /api/chat 200 in 46ms
[24] GET /api/chat 200 in 13ms
[25] GET /api/chat 200 in 20ms
[26] GET /api/chat 200 in 27ms
[27] GET /api/chat 200 in 34ms
[28] GET /api/chat 200 in 41ms
[29] GET /api/chat 200 in 48ms
[30] GET /api/chat 200 in 15ms
[31] GET /api/chat 200 in 22ms
[32] GET /api/chat 200 in 29ms
[33] GET /api/chat 200 in 36ms
[34] GET /api/chat 200 in 43ms
[35] GET /api/chat 200 in 50ms
[36] GET /api/chat 200 in 17ms
[37] GET /api/chat 200 in 24ms
[38] GET /api/chat 200 in 31ms
[39] GET /api/chat 200 in 38ms
[40] GET /api/chat 200 in 45ms
Show More
components/chat.tsx
"use client"
import * as React from "react"import { useChat } from "@ai-sdk/react"
import { Button } from "@/components/ui/button"import { Input } from "@/components/ui/input"
export function Chat() {  const [input, setInput] = React.useState("")  const { messages, sendMessage, status } = useChat()
  return (    <div className="flex flex-col gap-4">      {messages.map((message) => (        <div key={message.id}>          {message.parts.map((part, index) =>            part.type === "text" ? <p key={index}>{part.text}</p> : null          )}        </div>      ))}      <form        onSubmit={(event) => {          event.preventDefault()          sendMessage({ text: input })          setInput("")        }}      >        <Input value={input} onChange={(event) => setInput(event.target.value)} placeholder="Ask anything" />        <Button disabled={status !== "ready"}>Send</Button>      </form>    </div>  )}
Show More with Max Height
components/chat.tsx
"use client"
import * as React from "react"import { useChat } from "@ai-sdk/react"
import { Button } from "@/components/ui/button"import { Input } from "@/components/ui/input"
export function Chat() {  const [input, setInput] = React.useState("")  const { messages, sendMessage, status } = useChat()
  return (    <div className="flex flex-col gap-4">      {messages.map((message) => (        <div key={message.id}>          {message.parts.map((part, index) =>            part.type === "text" ? <p key={index}>{part.text}</p> : null          )}        </div>      ))}      <form        onSubmit={(event) => {          event.preventDefault()          sendMessage({ text: input })          setInput("")        }}      >        <Input value={input} onChange={(event) => setInput(event.target.value)} placeholder="Ask anything" />        <Button disabled={status !== "ready"}>Send</Button>      </form>    </div>  )}
Syntax Highlighting
app/api/chat/route.ts
import { streamText } from "ai"
export async function POST(request: Request) {  const { messages } = await request.json()
  const result = streamText({    model: "anthropic/claude-sonnet-4.5",    messages,  })
  return result.toUIMessageStreamResponse()}
Empty
Small
pnpm add ai @ai-sdk/react zod
$ pnpm add ai @ai-sdk/react zod
Progress: resolved 412, reused 398, downloaded 14, added 14, done
dependencies:
+ @ai-sdk/react 3.0.12
+ ai 6.0.12
+ zod 4.1.12
Done in 2.8s using pnpm v10.18.0
Small Destructive
TypeError: Cannot read properties of undefined (reading 'map')
    at MessageList (components/message-list.tsx:18:22)
    at renderWithHooks (react-dom.development.js:16305:18)
    at mountIndeterminateComponent (react-dom.development.js:20069:13)
Trace
$ pnpm add ai @ai-sdk/react zod
Progress: resolved 412, reused 398, downloaded 14, added 14, done
dependencies:
+ @ai-sdk/react 3.0.12
+ ai 6.0.12
+ zod 4.1.12
Done in 2.8s using pnpm v10.18.0
TypeError: Cannot read properties of undefined (reading 'map')
    at MessageList (components/message-list.tsx:18:22)
    at renderWithHooks (react-dom.development.js:16305:18)
    at mountIndeterminateComponent (react-dom.development.js:20069:13)
Typeset

Stream a response

Create a route handler that calls streamText and returns the stream to the client. The useChat hook reads it on the other side.

app/api/chat/route.ts
import { streamText } from "ai"
export async function POST(request: Request) {  const { messages } = await request.json()
  const result = streamText({    model: "anthropic/claude-sonnet-4.5",    messages,  })
  return result.toUIMessageStreamResponse()}

Then install the packages the route uses.

pnpm add ai @ai-sdk/react zod

The model streams text parts as they arrive, so the answer renders while it is written.

Wrap and Line Numbers
components/chat.tsx
"use client"
import * as React from "react"import { useChat } from "@ai-sdk/react"
import { Button } from "@/components/ui/button"import { Input } from "@/components/ui/input"
export function Chat() {  const [input, setInput] = React.useState("")  const { messages, sendMessage, status } = useChat()
  return (    <div className="flex flex-col gap-4">      {messages.map((message) => (        <div key={message.id}>          {message.parts.map((part, index) =>            part.type === "text" ? <p key={index}>{part.text}</p> : null          )}        </div>      ))}      <form        onSubmit={(event) => {          event.preventDefault()          sendMessage({ text: input })          setInput("")        }}      >        <Input value={input} onChange={(event) => setInput(event.target.value)} placeholder="Ask anything" />        <Button disabled={status !== "ready"}>Send</Button>      </form>    </div>  )}
Start Line
app/dashboard/page.tsx
  if (!session) {    redirect("/login")  }
  const projects = await db.project.findMany({    where: { ownerId: session.user.id },    orderBy: { updatedAt: "desc" },  })
  return <ProjectList projects={projects} />}
Diff, Wrap and Highlighting
app/api/projects/route.ts
export async function GET(request: Request) {  const { searchParams } = new URL(request.url, "http://localhost:3000/api/projects?include=owner,members")  const { searchParams } = new URL(request.url, process.env.NEXT_PUBLIC_APP_URL ?? request.headers.get("origin") ?? undefined)  const include = searchParams.get("include")?.split(",") ?? []  return Response.json(await getProjects({ include }))}
Header Edges
Title only
console.log("title, no actions")
$ pnpm add ai @ai-sdk/react zod
Progress: resolved 412, reused 398, downloaded 14, added 14, done
dependencies:
+ @ai-sdk/react 3.0.12
+ ai 6.0.12
+ zod 4.1.12
Done in 2.8s using pnpm v10.18.0
apps/web/app/(dashboard)/settings/organizations/[organizationId]/members/invitations/page.tsx
export default function Page() {}
Single Line and Empty
Install
pnpm dlx shadcn@latest add code-block
output.log
pnpm dev
Small Combinations
components/greeting.tsx
export function Greeting({ name }: Props) {  return <p>Hello, {name}</p>  return <p className="text-sm">Hello, {name}!</p>}
import { streamText } from "ai"
export async function POST(request: Request) {  const { messages } = await request.json()
  const result = streamText({    model: "anthropic/claude-sonnet-4.5",    messages,  })
  return result.toUIMessageStreamResponse()}
Streaming
app/api/chat/route.ts
import { streamText } from "ai"
export async function POST(request: Request) {  const { messages } = await request.json()
  const result = streamText({    model: "anthropic/claude-sonnet-4.5",    messages,  })
  return result.toUIMessageStreamResponse()}
pnpm dlx shadcn@latest add code-block
components/search.tsx
export function Search() {  const [query, setQuery] = React.useState("")  const results = useSearch(query)  const debounced = useDebounce(query, 300)  const results = useSearch(debounced)
  return <SearchResults results={results} />}
Markdown

Wrap the input in a useDebounce hook:

tsx
export function useDebounce<T>(value: T, delay = 300) {  const [debounced, setDebounced] = React.useState(value)
  React.useEffect(() => {    const timeout = setTimeout(() => setDebounced(value), delay)    return () => clearTimeout(timeout)  }, [value, delay])
  return debounced}

Then install it:

bash
pnpm dlx shadcn@latest add use-debounce
Languages
package.json
{  "name": "acme-chat",  "scripts": { "dev": "next dev --turbopack" },  "dependencies": { "ai": "^6.0.12", "zod": "^4.1.12" }}
app/globals.css
@import "tailwindcss";
:root {  --radius: 0.625rem;}
main.py
def greet(name: str) -> str:    return f"Hello, {name}!"
notes.txt
An unknown language renders as plain lines.
ANSI
$ pnpm test✓ src/format.test.ts (4 tests)✗ src/stream.test.ts (3 tests | 1 failed)
Tests  1 failed | 6 passed (7)
Card and Dialog
Install the AI SDK
Add the packages to your project.
Terminal
pnpm add ai @ai-sdk/react zod
Chat Answer
How do I stream a response?

Create a route handler that returns the stream:

app/api/chat/route.ts
import { streamText } from "ai"
export async function POST(request: Request) {  const { messages } = await request.json()
  const result = streamText({    model: "anthropic/claude-sonnet-4.5",    messages,  })
  return result.toUIMessageStreamResponse()}

The client reads it with useChat.

Tabs
app/api/chat/route.ts
import { streamText } from "ai"
export async function POST(request: Request) {  const { messages } = await request.json()
  const result = streamText({    model: "anthropic/claude-sonnet-4.5",    messages,  })
  return result.toUIMessageStreamResponse()}
RTL

أنشئ ملف المسار وأعد البث إلى العميل.

app/api/chat/route.ts
import { streamText } from "ai"
export async function POST(request: Request) {  const { messages } = await request.json()
  const result = streamText({    model: "anthropic/claude-sonnet-4.5",    messages,  })
  return result.toUIMessageStreamResponse()}