Recipe: FAQ bot with hot reload of source
Build a Q&A chatbot that ingests Markdown files and reloads answers live when you edit the source — no rebuild, no restart.
What you'll build
A single-page chatbot backed by a local Markdown knowledge base. Edit any .md file, hit save, and the bot picks up the change instantly via a file-watch loop. Answers stay grounded — no hallucination.
Stack
- Next.js 14 App Router (server + client)
- OpenAI chat completions (gpt-4o-mini)
- chokidar for file watching
- In-memory vector store (no Pinecone / Weaviate)
- Tailwind CSS
Architecture
pages/ api/chat/route.ts ← POST handler, RAG pipeline page.tsx ← chat UI lib/ store.ts ← in-memory doc store + watcher embed.ts ← embedding helper data/ faq/ ← your .md files live here
Step 1 — In-memory store with hot reload
On server start, glob data/faq/*.md, chunk each file by ## headings, embed with text-embedding-3-small, and store in a Map<string, Chunk[]>. A chokidar watcher re-indexes changed files on the fly.
Step 2 — RAG route handler
POST /api/chat accepts{ question: string }, embeds the question, runs cosine similarity against the store, picks the top 3 chunks, and sends them as context to the LLM with a strict system prompt: “Answer only from the provided context. If unsure, say you don't know.”
Step 3 — Chat UI
A minimal client component with a text input and message list. Messages stream via fetch +ReadableStream for token-by-token rendering. No websockets needed.
Why hot reload matters
Traditional RAG pipelines require a re-index step on every content change. With chokidar and an in-memory store, your bot stays in sync with your docs automatically. Edit a Markdown file, save, and the next question uses the updated content — zero friction for non-technical content editors.
Pro tip: Keep the store in a module-level variable so it survives HMR across route handler invocations. Use aglobalThisguard to avoid re-init on every hot reload in dev.