Starter prompts
ProA greeting and a grid of starter cards for the empty state of an AI app. The cards are grouped into Write, Code, Analyze and Plan tabs, and a shuffle swaps them with a short staggered crossfade. Picking a card fills the composer, and cards that use a connected app show its mark (Gmail, GitHub, Notion, Linear, Google Calendar).
What are we working on, Maya?
Pick a starter or write your own. Cards with an app mark use your connected tools.
- The empty state of a chat, copilot or agent, before the first message.
- Teaching what an assistant can do with connected tools, such as Gmail, GitHub or Notion.
- Onboarding a new workspace with a few tailored, ready to send prompts.
- Inside a running conversation; use follow-up suggestion chips in the chat thread instead.
- A command launcher with search; use command-palette or ai-command.
- A single inline suggestion in a text field; use ghost-text.
Installation
Pro source and install commands unlock with a Pro plan.
import { StarterPrompts } from "@/components/arc/starter-prompts/starter-prompts"; export function NewChat() { return ( <StarterPrompts greeting="Good morning, Maya" onSelect={prompt => track("starter_picked", { id: prompt.id })} onSubmit={async (message, { signal }) => { const res = await fetch("/api/chat", { method: "POST", body: JSON.stringify({ message }), signal }); if (!res.ok) throw new Error("Couldn't send. Try again."); }} /> );}Your own starters and tabs
<StarterPrompts categories={[{ id: "support", label: "Support" }, { id: "sales", label: "Sales" }]} prompts={[ { id: "refund", category: "support", app: "gmail", title: "Answer refund requests", description: "Draft replies for the 6 open threads", prompt: "Draft replies to the 6 open refund threads in Gmail..." }, { id: "pipeline", category: "sales", title: "Review the pipeline", description: "Deals that slipped this month", prompt: "List the deals that slipped in October and why..." }, ]} model={{ name: "GPT-6.1 Sol", mark: <OpenAIMark width={14} height={14} /> }}/>StarterPrompts
The empty state of an AI app: a greeting, starter cards filtered by category tabs, a shuffle that swaps cards with a short staggered crossfade, and a composer the cards fill. With no props it shows 24 sample starters and simulates the send.
greetingReactNode"What are we working on, Maya?"The heading.descriptionReactNodesample lineOne quiet line under the heading. Pass null to hide it.promptsStarterPrompt[]starterPromptSamplesThe starters: { id, category, title, description?, prompt, app? }. prompt is the full text placed in the composer; app is "gmail" | "github" | "notion" | "linear" | "calendar" and shows that app's mark.categoriesStarterPromptCategory[]Write, Code, Analyze, PlanThe filter tabs in order, each { id, label, icon? }. All is added in front, and tabs with no starters are hidden.defaultCategorystring"all"The tab selected first.countnumber4Cards on screen at once. The grid reserves this many slots so nothing jumps.loadingbooleanfalseShows placeholder cards with the same size and rhythm while starters load.valuestring–The composer text, controlled. Pair with onValueChange.defaultValuestring""The composer text on first render when uncontrolled.onValueChange(value: string) => void–Called when the composer text changes, from typing or a picked card.onSelect(prompt: StarterPrompt) => void–Called when a card is picked, after its prompt fills the composer.onSubmit(message: string, context: { prompt: StarterPrompt | null; signal: AbortSignal }) => Promise<void> | void–Sends the message. Throw to show the error state with Retry. The signal aborts when the person presses Stop or the component unmounts. Without it the send is simulated.model{ name: string; mark?: ReactNode }{ name: "Claude Sonnet 5.5" }The model named in the composer footer. The mark defaults to the Claude mark.placeholderstring"Ask anything, or pick a starter above"Composer placeholder.classNamestring–Extra class on the root section.- Tab
- Moves through the tabs, Shuffle, each card and the composer.
- Arrow keys
- Move between category tabs.
- EnterorSpace
- On a card, fills the composer with its prompt and focuses it.
- Enter
- In the composer, sends the message.
- Shift Enter
- In the composer, adds a new line.
- Escape
- While sending, stops the send and keeps the text.
- The component is a labelled section; the greeting is its heading.
- Each card is a button whose name includes the title, the connected app and the category.
- A polite live region announces picks, shuffles, sending, done and errors, and says when a send is simulated.
- Status is never color alone: done shows a check and label, errors an alert icon and the message.
- The send button is labelled Send message, and Stop sending while a message is in flight.
- Shuffle and tab changes crossfade each card's content inside a fixed frame: out in 100ms, in over 160ms with a 2px rise, staggered 35ms per card (about 100ms in total).
- Picking a card focuses the composer and fades the new text in over 160ms.
- The footer status and the send or stop icon crossfade; nothing moves or resizes.
- Reduced motion keeps every end state and cuts the fades and the skeleton breathing.
- Two columns of cards above about 560px of container width, one column below.
- Tabs scroll inside themselves with edge fades; Shuffle becomes an icon button under about 440px.
- Padding and the outer radius step down under 480px of viewport width. Holds at 360px with no horizontal scroll.
- Renders only the cards on screen; the pool can hold hundreds of starters.
- No timers or loops while idle; the skeleton uses one CSS animation.
- Marks are inline SVG, no images to load.
Notes for AI
Give your coding assistant the Markdown reference instead of screenshots.
- Use it as the first screen of a new chat or agent thread, then swap it for the conversation once a message is sent.
- Keep titles short and verb first, and put the full, specific instruction in prompt; the composer shows prompt, not title.
- Set app only when the prompt really uses that integration, so the mark means something.
- Wire onSubmit to your chat endpoint and honor the AbortSignal for Stop.
The full library index for assistants is at /llms.txt.