Conversation title is auto-generated or set on creation
Why it matters
A history sidebar full of rows labeled "New conversation" or UUIDs is functionally useless — users cannot find anything, so they start a new chat every time instead of continuing old ones, which defeats the point of persistence entirely. Auto-generated titles turn the archive from a dead dump into a searchable, scannable record of prior work, and they cost roughly a fraction of a cent per conversation when generated by a cheap model like gpt-4o-mini or claude-haiku.
Severity rationale
Info because it is polish, not a functional blocker — users can still operate without titles.
Remediation
After the first assistant response lands, fire a background call to a cheap model asking for a six-word title summarizing the opening exchange. Persist via UPDATE conversations SET title = $1 WHERE id = $2. Fall back to the first fifty characters of the user's opening message if the generation fails. Implement in src/lib/ai/generate-title.ts.
const { text } = await generateText({ model: openai('gpt-4o-mini'), prompt: `Six-word title for: "${firstMessage.slice(0, 200)}"` })
await updateConversationTitle(id, text.trim())
Detection
-
ID:
conversation-title -
Severity:
info -
What to look for: Count all conversations visible in the history list or sidebar. For each, enumerate the title source: auto-generated by AI, truncated from first message, user-provided, or generic default ("Untitled", "New conversation", UUID). Check for title generation logic: API calls that summarize the first exchange, first-message truncation functions, or user-rename handlers. At least 1 title generation mechanism must produce a maximum 50-character descriptive title.
-
Pass criteria: Conversations in the history list have human-readable titles — either auto-generated, derived from the first message, or user-provided. Titles must be descriptive and under 60 characters. Report on pass: "Title generation uses X method."
-
Cross-reference: For conversation persistence patterns including database schema for conversation metadata, see the Data Persistence Fundamentals in the Accessibility Fundamentals Audit.
-
Fail criteria: All conversations in history are titled "Untitled", "New conversation", or display a raw UUID/ID — making it impossible to identify conversations at a glance.
-
Skip (N/A) when: Same as
conversation-organization— single-session application with no persisted history. -
Detail on fail:
"Conversation history present but titles default to 'New conversation' or UUID — no auto-title generation or first-message truncation logic found". -
Remediation: Auto-title is a small but high-impact quality-of-life feature. A simple approach:
// After first AI response, generate a title const generateTitle = async (firstMessage: string) => { const { text } = await generateText({ model: openai('gpt-4o-mini'), // Use cheap model for titles prompt: `Generate a short, descriptive title (max 6 words) for a conversation that starts with: "${firstMessage.slice(0, 200)}"`, }) await updateConversationTitle(conversationId, text.trim()) }Or simply use the first 50 characters of the first message:
const title = firstUserMessage.slice(0, 50) + (firstUserMessage.length > 50 ? '...' : '')
Taxons
History
- 2026-04-18·v1.0.0·Initial import from ai-ux-patterns·automated