Agent answer with inline citation chips that show the source on hover, and a collapsible list of the sources behind it. Reads [1]-style markers and AI SDK source-url parts.
Set your access key from API keys as NEXTUI_TOKEN in .env.local and add the @nextui namespace below to components.json once. Then every item installs by name. Each install counts as a copy on a free account.
$pnpm dlx shadcn@latest add @nextui/sources
1{2"registries": {3"@nextui": {4"url": "https://nextui.dev/r/{name}.json",5"headers": { "Authorization": "Bearer ${NEXTUI_TOKEN}" }6}7}8}
1"use client";23import type { UIMessage } from "ai";4import { Sources } from "@/components/nextui/sources";56// Ask the model to cite with [1], [2] markers in the order of the sources it used.7// On the server, send sources with toUIMessageStreamResponse({ sendSources: true }).8export function AssistantMessage({ message }: { message: UIMessage }) {9const text = message.parts.flatMap((p) => (p.type === "text" ? [p.text] : [])).join("");10const sources = message.parts.flatMap((p) =>11p.type === "source-url" ? [{ url: p.url, title: p.title }] : [],12);1314return <Sources answer={text} sources={sources} />;15}
| Prop | Type | Default | Description |
|---|---|---|---|
| answer | string | – | Answer text; markers like [1] or [2][3] become citation chips |
| sources | { url: string; title?: string; snippet?: string }[] | – | Sources in citation order: [1] is the first one |
| label | string | "N sources" | Text of the list toggle |
| defaultOpen | boolean | false | Start with the source list open |
| open | boolean | – | Controlled open state of the list |
| onOpenChange | (open: boolean) => void | – | Called when the list opens or closes |
| autoPlay | boolean | false | Stream the answer and open the list on a loop, for demos |
| className | string | – | Extra classes on the wrapper |
Sign in to see the code
Preview it freely. A free account copies code and prompts a few times a day.