Browse all components
Source Card UI
A cited source as a card — favicon, page title, domain, and the snippet the answer actually drew from.
Preview
Agent promptClaude Code · Cursor · any agent
Add the Source Card UI component from the Scrim UI registry to this project and use it in the configuration described below.
Source Card UI — A cited source as a card — favicon, page title, domain, and the snippet the answer actually drew from.
## 1. Install
```bash
npx shadcn@latest add @scrimui/source-card
```
This writes a single file to `components/ui/source-card.tsx`. It is plain React + Tailwind with no runtime dependencies — no Radix, no CVA, nothing to add to package.json. If this project does not use the shadcn CLI, copy the source from https://scrimui.dev/components/source-card to the same path by hand; nothing in the file depends on shadcn.
## 2. Use it
```tsx
import { SourceCard } from "@/components/ui/source-card";
<SourceCard
index={1}
title="Claude Fable 5 and Mythos 5"
url="https://www.anthropic.com/news/claude-fable-5-mythos-5"
domain="anthropic.com"
snippet="Fable 5 is the most advanced generally available Claude model; Mythos 5 is restricted to approved organizations."
/>
```
## 3. The configuration that matters
This is the component's "With snippet" state — Two lines of context help the reader judge relevance before clicking.
Every prop is at its default value. Keep the call site minimal — do not write out default values.
Reference: https://scrimui.dev/components/source-cardFollows the props below — change a control and the prompt changes with it, so an agent reproduces that configuration instead of the defaults.
Install
npx shadcn@latest add @scrimui/source-cardComponent source
React + Tailwind component using your shadcn theme. No additional component dependencies.
"use client";
import * as React from "react";
/* ------------------------------------------------------------------ */
/* Types */
/* ------------------------------------------------------------------ */
export type SourceCardProps = {
title: string;
url: string;
domain?: string;
snippet?: string;
favicon?: string;
index?: number;
className?: string;
};
/* ------------------------------------------------------------------ */
/* Helpers */
/* ------------------------------------------------------------------ */
function domainFromUrl(url: string) {
try {
return new URL(url).hostname.replace(/^www\./, "");
} catch {
return url;
}
}
/* ------------------------------------------------------------------ */
/* SourceCard */
/* ------------------------------------------------------------------ */
export function SourceCard({
title,
url,
domain,
snippet,
favicon,
index,
className = "",
}: SourceCardProps) {
const host = domain ?? domainFromUrl(url);
return (
<a
href={url}
target="_blank"
rel="noreferrer noopener"
className={`group block rounded-xl border border-border shadow-sm bg-card p-4 transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring hover:border-border hover:bg-muted ${className}`}
>
<div className="flex items-start gap-3">
{favicon ? (
// eslint-disable-next-line @next/next/no-img-element
<img
src={favicon}
alt=""
className="h-5 w-5 shrink-0 rounded"
width={20}
height={20}
/>
) : (
<span
className={`flex h-5 w-5 shrink-0 select-none items-center justify-center rounded text-xs font-medium bg-muted text-muted-foreground`}
>
{title.slice(0, 1).toUpperCase()}
</span>
)}
<div className="min-w-0 flex-1">
<p className="truncate text-sm font-medium text-foreground leading-5">
{title}
</p>
<p className="mt-0.5 text-xs text-muted-foreground">{host}</p>
{snippet && (
<p className="mt-3 line-clamp-2 text-sm leading-5 text-muted-foreground">
{snippet}
</p>
)}
</div>
{index !== undefined && (
<span className="ml-auto flex h-5 w-5 shrink-0 items-center justify-center rounded bg-muted text-xs font-medium text-muted-foreground">
{index}
</span>
)}
</div>
</a>
);
}
When to use it
- Always show the domain — it's the fastest relevance signal, before the title or snippet.
- Number cards so the answer text can cite them with plain [1][2] markers.
- Open in a new tab with rel="noreferrer noopener" — sources are third-party destinations.
- Keep snippets to two lines; truncate rather than expanding the card.
- Fall back to a colored letter avatar when a favicon isn't available — never a broken image icon.
What breaks in production
- Hiding the source until hover — citations only work when the source is glanceable.
- Showing favicon-less broken images; always have a graceful fallback.
- Making the whole card a link that swallows the citation number as the anchor.
- Dropping the snippet in a full-screen modal instead of an inline card.
Related Components
The passages retrieval actually returned, with similarity scores and a visible relevance floor — including the case where nothing cleared it.
Inline citation markers in generated text — numbered footnotes that reveal the source in a hover preview card.
A citation marker that shows the passage it came from — fixed positioning that survives a scrolling answer, touch and keyboard, and an honest state for a number the model invented.
The message input at the heart of an AI chat app — file attachments, model picker, tool toggles, voice, and a send button that turns into stop.