AI Tutor — New Chat & Search Chats¶
Status: in-progress LNO: L — Leverage (fixes the primary entry to the core AI surface; unblocks topic compartmentalization) Owners: @kantharajucn Last updated: 2026-06-21 Roles affected: Learner · Trainer · Parent · B2C User Primary routes:
/new-chat,/history,/ai-tutor/c/:conversationIdSource of the ask: Self-initiated — product owner dogfooding (2026-06-21); could not find a way to start a fresh chat. Competitive parity with claude.ai, ChatGPT, Perplexity.
TL;DR¶
The AI Tutor auto-resumes the last conversation when you open it, and the only "New chat" control is buried inside a sidebar that's closed by default — so users get stuck in one ever-growing thread with no obvious way out. This feature makes "New Chat" always open a clean composer (no prior messages), renames the discovery surface to "Search Chats" (a date-grouped, searchable list you click to continue a past session), and adds a + New chat affordance inside the chat header. It deliberately reverses the shipped auto-resume-on-entry behavior ([[ai-tutor-resume-conversation]]), which was flagged as an unvalidated guess.
Why this exists¶
Who asked for it¶
- Primary source: Self-initiated — the product owner, dogfooding on 2026-06-21, opened the chat and could not figure out how to start a new session; every entry loaded the previous one. Reference patterns provided: claude.ai (New chat + Chats), Perplexity (New
+at top of nav, History below). - Corroborating signal: [[ai-tutor-resume-conversation]] (shipped 2026-06-09) explicitly self-flagged: "the preference for auto-resume over showing a blank box is a reasoned guess pending broader validation." The product owner's inability to start fresh is that validation arriving — the guess increased friction more than it helped.
What user pain does it solve¶
Rahul, a 2nd-year learner, finishes a chat asking for help with a calculus problem. The next day he wants to ask about photosynthesis for biology. He clicks Chat in the sidebar and is dropped straight back into the calculus thread — no blank box, no obvious "start over." He scrolls to the bottom, unsure whether to just keep typing in the old thread or hunt for a new-chat button (which lives inside a sidebar that's closed by default). He ends up mixing two unrelated subjects in one conversation, which muddies the tutor's context and his own ability to find either later.
The mental model users bring from ChatGPT/claude/Perplexity is: "Chat/New" = a clean slate; my past chats are a click away in a list I can search. The app inverts that.
Cost of not doing it¶
- Near-term: Every user who wants to switch topics either pollutes an existing thread or gives up looking for "new chat." Conversations become unsearchable blobs; the (already-built)
/historypage goes undiscovered because it's labeled "History" and never surfaced from the chat. - Long-term: The AI Tutor is the core surface of the platform. If its most basic interaction (start a fresh question) fights the muscle memory users bring from every other AI product, it erodes trust in the whole product right at the primary touchpoint.
Validation¶
- Strong on the discoverability defect: the product owner — the person who knows the app best — could not start a new chat. If they can't, learners can't.
- Weaker on the exact grouping/search choices: those are reasoned parity decisions (claude.ai/Perplexity), not user-tested. Acceptable because most of this is surfacing capability that already exists (the searchable
/historypage,startNewConversation), not net-new behavior. The one genuinely reversed decision (auto-resume) was itself an unvalidated guess.
Personas¶
- Rahul, 2nd-year CSE learner. Uses the tutor across multiple subjects in a week. Brings ChatGPT muscle memory: expects "New chat" to be one obvious click and his old chats to be searchable by name.
- Dr. Anita, CSE Sem-4 lecturer. Uses the tutor for lesson ideas and quick explanations. Wants to reopen "that chat where I drafted the OS quiz" by name, not by scrolling.
ICP exclusions¶
- Mobile app users — this phase is web (
apps/web) only; React Native parity is a separate track. - Backend search at scale — users with thousands of conversations are out of scope for Phase 1 (client-side search over the most-recent set; see Non-goals).
Outcomes for the user¶
- Clicking New Chat always opens a clean composer — Rahul never lands in yesterday's calculus thread by accident.
- A
+ New chatis visible inside the chat at all times — no need to open a hidden panel to start over. - Search Chats lets Rahul type "photosynthesis" and jump straight to that past conversation.
- Past chats are grouped by recency (Today / Yesterday / …) so "what was I just doing" is the first thing he sees.
Non-goals¶
- Not adding a second persistent left sidebar inside the chat (claude.ai-style rail). Kwilo already has a global platform nav; a second rail would mean two left sidebars. We enhance the global nav (Perplexity model) instead.
- Not building server-side / full-text history search in this phase. Search stays client-side over the conversations already loaded.
- Not changing how conversations are titled, renamed, pinned, or deleted (row actions remain as-is; see [[history-tab]]).
- Not re-grouping the
/historypage by subject/topic — date grouping only for now. - Not touching the B2C paywall/quota slots in the chat sidebar.
Metrics¶
- North star: new conversations created per active user per week goes up (users compartmentalize topics instead of one growing thread). Proxy: distribution of messages-per-conversation tightens (fewer mega-threads).
- Guardrail: no drop in overall chat engagement (messages sent / WAU) — removing auto-resume must not make people lose their place so badly they disengage. Reopen-from-Search-Chats events should absorb the old resume traffic.
Mental model¶
Global nav (Perplexity-style)
+ New Chat → always a clean composer (/new-chat, no prior messages)
🔍 Search Chats → searchable, date-grouped list (/history)
click a row → continue that conversation (/ai-tutor/c/:id)
Inside a chat
[ + New chat ] in the header → startNewConversation (clean slate)
Invariant: entering the chat never silently resumes a past conversation. Resuming is always an explicit user action (click a row in Search Chats, or a deep link to /ai-tutor/c/:id).
User flows¶
Happy path — Rahul switches subjects¶
- Rahul clicks New Chat in the sidebar → lands on
/new-chatwith an empty composer (no calculus thread). - Asks his photosynthesis question; the conversation is created and persisted as usual.
- Next week he clicks Search Chats, types "calculus" → his old thread appears under Previous 7 days; he clicks it and continues where he left off.
Edge cases¶
- First-time user:
/new-chatis already the clean composer; Search Chats shows the existing empty state. - Deep link / hard reload of
/ai-tutor/c/:id: still opens that specific conversation (unchanged). - Mid-chat "New chat": the header
+ New chatclears the current thread and navigates to a fresh/new-chat.
Design decisions¶
Decision 1: New Chat always starts fresh (remove auto-resume-on-entry)¶
Chose: /new-chat renders the chat composer fresh every time. The NewChatRoute resume gate is removed.
Why: Auto-resume was the direct cause of "I can't start a new chat." It was shipped as an explicit, self-flagged guess ([[ai-tutor-resume-conversation]]); the product owner's dogfooding is the validation that it cost more than it gave. Resuming is preserved as an explicit action via Search Chats and deep links, so nothing is truly lost — only the surprising default is.
Alternatives rejected: - Keep auto-resume, just add a visible +New — leaves the surprising default in place; users still land in the wrong thread first. - Landing screen with greeting + recents on entry — more build, and the global nav already gives a home + the Search Chats entry; deferred.
Decision 2: Enhance the global nav (Perplexity), not a claude.ai in-chat rail¶
Chose: Rename the global nav entries — Chat → "New Chat", History → "Search Chats" — and keep history on the existing /history page. Add a + New chat button only in the chat header.
Why: claude.ai/Perplexity own a single sidebar because they are the chat app. Kwilo is a platform with a global nav already carrying Chat/History/Courses/Assignments. Perplexity's pattern (New + at top, History below) maps 1:1 onto that nav. A second in-chat rail would create two stacked left sidebars and a double-nav problem.
Alternatives rejected: - Persistent claude-style in-chat sidebar — two left sidebars; rejected for a multi-surface platform. - Both — maximal redundancy and maintenance for no added clarity.
Decision 3: Group Search Chats by date; search stays client-side¶
Chose: Group the list into Today / Yesterday / Previous 7 days / Previous 30 days / Older. Keep the existing client-side title search.
Why: Date grouping matches "what was I just doing," the dominant reopen intent (claude.ai/ChatGPT convention). Client-side search ships now with zero backend change over the already-loaded conversations.
Alternatives rejected:
- Group by subject/topic — appealing for a learning tool, but needs reliable subject tagging; deferred.
- Keep grouping by mode — mode sections answer "what kind of artifact," not "when did I last touch this"; less useful for reopening.
- Server-side search now — needs a new ?q= endpoint + indexing; deferred until history volume justifies it.
Risks and mitigations¶
- Risk: Users who liked auto-resume lose their place on reload. Mitigation: Search Chats is one click away, sorted most-recent-first, so the just-left thread is the top row. Watch the guardrail metric.
- Risk: "Search Chats" label is unfamiliar vs. the conventional "History." Mitigation: It's the explicit ask; the magnifying-glass affordance + date groups make intent obvious. Revisit if support asks "where's my history."
- Risk: Removing
NewChatRoutebreaks intent/prefill flows that relied on its bypass. Mitigation: Those flows renderAITutorPagedirectly anyway; with no gate there's nothing to bypass. Covered by the existing AITutorPage entry tests.
Rollout plan¶
Phase 1 — New Chat fresh + Search Chats date grouping (this PR, ~moderate)¶
- Remove the auto-resume gate:
/new-chat→AITutorPagedirectly; deleteNewChatRoute+newChatResume+ their tests. - Rename nav labels:
nav.chat→ "New Chat" (with a new-chat icon),nav.history→ "Search Chats". - Add
+ New chatto the chat header, wired tostartNewConversation. - Search Chats (
/history): group by date instead of mode; client-side search unchanged.
Explicitly deferred to Phase 2:
- Server-side history search (?q=).
- Recents peek on the New Chat screen.
- Subject/topic grouping; row actions (rename/pin).
Success signals¶
What good looks like¶
- A hallway test: "start a new chat" — the user clicks New Chat without hesitation and gets a blank composer. "Find your chat about X" — they click Search Chats, type X, open it. Zero "where do I…?" moments.
Observable signals¶
- New-conversations-per-user rises; mega-threads (very high message counts) shrink as a share of activity.
- Search Chats page views and reopen-from-row events rise and absorb the removed auto-resume traffic.
- No uptick in support asking "how do I start a new chat" or "where's my history."
Sean Ellis counterfactual¶
If we reverted this a week after shipping — auto-resume back, "New Chat"/"Search Chats" renamed back to "Chat"/"History," the header + gone — the product owner and dogfooding users would notice within minutes and complain with specifics ("it dumped me in my old thread again," "where did New Chat go"). That's the signal the change is load-bearing.
Open questions¶
- [ ] Do we want a small "recent chats" peek on the New Chat screen, or is the Search Chats nav entry enough? (Leaning: nav entry is enough for Phase 1.)
- [ ] Is "Search Chats" the right label, or just "Chats"? (Going with the product owner's explicit "Search Chats" for now.)
Changelog¶
- 2026-06-21 — Doc created. Phase 1 scoped: New Chat always fresh, Search Chats date grouping, header
+ New chat. Supersedes the auto-resume-on-entry decision in [[ai-tutor-resume-conversation]].
Appendix: Reference¶
Routes¶
| Route | Component | Purpose |
|---|---|---|
/new-chat |
AITutorPage (was NewChatRoute) |
Always a fresh chat composer |
/history |
HistoryPage |
"Search Chats" — searchable, date-grouped list |
/ai-tutor/c/:conversationId |
AITutorPage |
Open/continue a specific conversation |
Key files¶
apps/web/src/routes/ProtectedRoutes/SharedRoutes.tsx—/new-chatnow rendersAITutorPageapps/web/src/constants/navigation.ts—nav.chat/nav.historylabels + iconsapps/web/src/pages/shared/AITutorPage/components/ChatHeader.tsx—+ New chataffordanceapps/web/src/pages/shared/HistoryPage/helpers.ts—groupConversationsByDateapps/web/src/i18n/locales/en/nav.json— "New Chat" / "Search Chats" labels- Removed:
NewChatRoute.tsx,newChatResume.ts(+ tests)