AI Chatbot Feature
Add a real AI chat feature with streaming responses, conversation history, and graceful failure handling.
The route
6 steps to Done
- 01
Define the assistant spec
Decide what the assistant does, its boundaries, and its system prompt.
Preview prompt + verify gate ▾ Hide ▴
Define the AI assistant spec for this app. Specify: what the assistant helps with (its scope) and what it should refuse; the exact system prompt text; which LLM provider/model is used and where the API key lives (backend env var only); the conversation model (conversation id, messages with role/content/timestamp, owner); and limits (max message length, history window sent to the model). Do not implement yet.
- ✓ System prompt text is written out
- ✓ Key location is backend env only
- ✓ Conversation/message model is defined
- 02
Build the chat UI
A trustworthy chat surface with all interaction states.
Preview prompt + verify gate ▾ Hide ▴
Build the chat interface. Requirements: scrollable message list with distinct user/assistant styling; input with send button and Enter-to-send; send disabled while a response is pending; a typing indicator while waiting; auto-scroll to the newest message; an empty state introducing the assistant; timestamps; mobile responsive layout. Wire it to local state for now - the real API comes next.
- ✓ Send disables while pending
- ✓ Typing indicator renders
- ✓ Auto-scroll works on new messages
- 03
Integrate the real LLM API
Replace nothing with something: real model responses through the backend.
Preview prompt + verify gate ▾ Hide ▴
Implement the backend chat endpoint with the real LLM. Requirements: the frontend posts the message to our backend; the backend calls the LLM API with the system prompt and recent history window, using the key from environment variables; the response is returned to the UI (stream it if supported, otherwise show the typing indicator until complete); errors from the API map to a visible UI error with a retry button - never an infinite spinner. Prove it is real by asking something no canned array could answer.
- ✓ Responses are genuinely from the model
- ✓ The key is absent from all frontend code
- ✓ API failure shows a retry-able error, not a stuck spinner
- 04
Persist conversation history
Chats must survive refresh and be scoped to their owner.
Preview prompt + verify gate ▾ Hide ▴
Implement history persistence. Requirements: store every user and assistant message in the database under a conversation id and owner; on load, restore the active conversation; support starting a new conversation and listing past ones with titles (first message snippet); include the recent history window in each LLM call so the assistant has context; verify context by referencing something said earlier in the chat.
- ✓ Refresh restores the conversation
- ✓ The assistant remembers earlier messages
- ✓ New conversation starts clean
- ✓ Users see only their own conversations
- 05
Harden failure and limit handling
AI features fail in production - make every failure visible and recoverable.
Preview prompt + verify gate ▾ Hide ▴
Harden the chat. Requirements: handle API timeout, rate limit, and server errors with distinct friendly messages and a retry action that resends the failed message; enforce max message length with an inline counter/error; prevent empty sends; if the model returns nothing, show a fallback message rather than a blank bubble; log failures server-side. Simulate at least one failure (bad key or forced error) to prove the UI path.
- ✓ A simulated API failure shows the error UI
- ✓ Retry resends the failed message
- ✓ Overlong/empty messages are blocked inline
- 06
Chat QA pass
Verify realness, persistence, and resilience end to end.
Preview prompt + verify gate ▾ Hide ▴
Run chat QA and report PASS/FAIL with evidence: a novel question gets a real model answer; follow-up shows context memory; refresh restores history; new conversation isolates cleanly; forced API failure shows recoverable error; rapid double-send is blocked; mobile layout works. Fix all failures and re-run.
- ✓ Context memory demonstrated
- ✓ Forced failure path verified
- ✓ History persistence verified via refresh
- ✓ All failures fixed