First-run state An empty conversation composed around the input: what the assistant can see, a few examples, a stated limitation, and what happens to what you type. Nothing here needs dismissing, because everyone who is not new sees it four hundred times. npx shadcn@latest add button textarea npm i lucide-react Tokens this needs: --background, --card, --card-foreground, --primary, --primary-foreground, --accent, --accent-foreground, --muted-foreground, --border, --input, --status-warn The status, chart, scale, state and direction names are an extension, not a rename. shadcn has --destructive and five --chart-* and nothing else in this territory. ──────────────────────────────────────────────────────────────────────── // FirstRunState.tsx ──────────────────────────────────────────────────────────────────────── import { useRef, useState } from "react"; import { ArrowUp } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Textarea } from "@/components/ui/textarea"; type Props = { /** One line on what the assistant can see. Scope is the thing a viewer * cannot guess, and the reason to use this over a chatbot. */ scope: string; /** Two or three. More than that is a menu, and a menu is a thing to read. */ examples: string[]; /** Stated up front. It reads as an apology and prevents the failure that * actually loses people. */ limitation: string; /** What happens to what gets typed. Asked at the moment of first input, * not on a settings page. */ dataNotice: string; onSend: (text: string) => void; }; export function FirstRunState({ scope, examples, limitation, dataNotice, onSend }: Props) { const [draft, setDraft] = useState(""); const ref = useRef(null); const send = () => { const text = draft.trim(); if (!text) return; onSend(text); setDraft(""); }; // An example fills the input rather than sending. A newcomer is here to // learn what a question looks like, and a question they can edit teaches // that better than one that fires on click. const useExample = (text: string) => { setDraft(text); ref.current?.focus(); }; return (

Ask about anything in this workspace

{scope}

{examples.map((e) => ( ))}
{/* The input is the centre. Everything else on this screen has to be quieter than it, so a veteran can skip the whole composition. */}