# AI Chatbot for Your Docs (RAG)

> Chat with your own Markdown docs: answers grounded in your content, with sources, streaming replies and an "I don't know".

- Category: AI
- Version: 1.0
- Source: https://wonly.dhfm.in/builder-4392ac/docs-chatbot-rag/

## Overview

Turn a folder of Markdown docs into a chatbot that answers only from your content and shows its sources. It uses retrieval-augmented generation (RAG): your docs are split into chunks, embedded and stored in Postgres with pgvector, and the most relevant chunks are given to the model for each question.

Includes a Context7 MCP so your AI coding tool uses the current AI SDK docs instead of guessing.

Before you start: Node.js 20+, a Supabase project, an OpenAI API key and Claude Code or Cursor. About 2.5 hours.

## Tech stack

- AI SDK
- Next.js
- OpenAI
- pgvector
- Supabase

## Build steps

### 1. Create the app and add the docs MCP

Run npx create-next-app@latest docs-bot (TypeScript, App Router, Tailwind). Save CLAUDE.md, add the Context7 MCP, and put your Markdown docs in a /docs folder (start with 5–20 files).

Prompt:

```text
Read CLAUDE.md. Use context7 to look up the current AI SDK docs for: streaming chat in a Next.js App Router route handler, the React chat hook, and embedding many values with OpenAI. Summarise the exact imports and function names for the current version. Do not write app code yet.
```

**Done when:** You have a short summary of the current AI SDK API from Context7.

### 2. Create the vector database

Run supabase-schema.sql in Supabase → SQL Editor. Add OPENAI_API_KEY, NEXT_PUBLIC_SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY to .env.local (never commit it).

Prompt:

```text
Save the schema as supabase/schema.sql. Create lib/supabase-admin.ts with a server-only Supabase client using the service role key (import "server-only" so it can never reach the browser).
```

**Done when:** The documents table and match_documents function exist; npm run build passes.

### 3. Ingest your docs

A script reads /docs, splits by headings into ~800-token chunks with overlap, embeds them in batches and upserts into documents.

Prompt:

```text
Write scripts/ingest.ts (run with npx tsx scripts/ingest.ts): read all .md/.mdx files in /docs, split by headings then into ~800-token chunks with 100-token overlap, embed with text-embedding-3-small in batches using the AI SDK, and upsert into documents on (source, chunk_index). Delete old chunks of a file before re-inserting it. Print files, chunks and estimated tokens.
```

**Done when:** Running the script fills the documents table; running it again does not create duplicates.

### 4. Retrieval

Embed the question and fetch the closest chunks with match_documents.

Prompt:

```text
Create lib/retrieve.ts: embed the question with the same model, call rpc("match_documents") with match_count 6 and min_similarity 0.3, and return chunks with source and similarity. Add a tiny test page /debug/search (dev only) that shows the chunks for a query.
```

**Done when:** Searching a topic from your docs returns the right chunks at the top.

### 5. Streaming chat route

The model answers only from retrieved context and lists sources.

Prompt:

```text
Create the chat route handler using the current AI SDK streaming API (check with context7). For the latest user message: retrieve chunks, then stream an answer with a system prompt that says: answer only from the context below, quote sources by file name, and if the context does not contain the answer say "I don't know based on these docs". Send the list of sources to the client with the response.
```

**Done when:** A request to the route streams a grounded answer.

### 6. Chat interface

A clean chat with streaming text, sources under each answer and suggested questions.

Prompt:

```text
Build the chat page with the current AI SDK React chat hook: message list, input, stop button, streaming text, and under each answer the source files as small links. Show 3 suggested questions when the chat is empty. Make it work on mobile.
```

**Done when:** You can ask questions and see answers stream with sources.

### 7. Test with 10 real questions

Measure before you polish. Fill in eval.md with questions you know the answers to.

Prompt:

```text
Read eval.md. For each question, call the chat route and record the answer and sources in a table. Mark which ones are wrong and suggest fixes (chunk size, min_similarity, system prompt). Apply the safest fix and re-run.
```

**Done when:** At least 8 of 10 answers are right, and the out-of-scope question gets "I don't know".

### 8. Limits and deploy

Protect your API key from abuse, then deploy.

Prompt:

```text
Add a simple per-IP rate limit to the chat route (e.g. 20 requests per 10 minutes, in-memory is fine for one server; explain options for production), cap the question length, and log token usage. Then list the env vars for Vercel and deploy.
```

**Done when:** The bot is live, and rapid repeated requests get a polite "slow down" message.

## Assets

### CLAUDE.md — Project root. Cursor: save as AGENTS.md.

```
# CLAUDE.md — Docs chatbot (RAG)

## Stack
- Next.js (App Router, TypeScript)
- AI SDK (`ai` package) for streaming chat and embeddings
- Supabase Postgres + pgvector (`supabase/schema.sql`)
- OpenAI `text-embedding-3-small` (1536 dimensions) for embeddings

## Rules
- The AI SDK changes often. Before writing AI SDK code, use the Context7 MCP to read the current docs ("use context7").
- Secrets live in `.env.local` only: `OPENAI_API_KEY`, `NEXT_PUBLIC_SUPABASE_URL`, `SUPABASE_SERVICE_ROLE_KEY`. The service role key is server-only; never import it into client components.
- Ingestion is a script (`scripts/ingest.ts`), not an API route.
- Chunks: about 800 tokens with 100 tokens overlap, split on headings first.
- Answers must come from retrieved chunks. If nothing relevant is found, say so. Always list the sources used.
- After each step run `npm run build` and fix all errors.
```

### supabase-schema.sql — pgvector table, HNSW index and match_documents function.

```
-- Docs chatbot: run in Supabase → SQL Editor.
create extension if not exists vector with schema extensions;

create table public.documents (
  id bigint generated always as identity primary key,
  source text not null,              -- file path or URL the chunk came from
  chunk_index int not null,
  content text not null,
  embedding extensions.vector(1536) not null,   -- text-embedding-3-small
  unique (source, chunk_index)
);

create index documents_embedding_idx
  on public.documents using hnsw (embedding extensions.vector_cosine_ops);

-- RLS on, no policies: only the server (service role key) reads and writes.
alter table public.documents enable row level security;

create or replace function public.match_documents(
  query_embedding extensions.vector(1536),
  match_count int default 6,
  min_similarity float default 0.3
)
returns table (id bigint, source text, content text, similarity float)
language sql stable
set search_path = public, extensions
as $$
  select d.id, d.source, d.content, 1 - (d.embedding <=> query_embedding) as similarity
  from public.documents d
  where 1 - (d.embedding <=> query_embedding) > min_similarity
  order by d.embedding <=> query_embedding
  limit match_count;
$$;
```

### Context7 MCP — Up-to-date library docs for your AI. Add an API key from context7.com for higher limits.

Source: https://wonly.dhfm.in/builder-4392ac/docs-chatbot-rag/context7-mcp/

Review this config before installing: it runs a command on your machine.

```json
{
    "mcpServers": {
        "context7": {
            "command": "npx",
            "args": [
                "-y",
                "@upstash/context7-mcp"
            ]
        }
    }
}
```

### Vercel AI SDK — The SDK used for streaming chat and embeddings.

https://github.com/vercel/ai

### Supabase AI & Vectors docs

https://supabase.com/docs/guides/ai

### eval.md — Your 10-question test sheet.

```
# eval.md — 10 questions to test your chatbot

Write 10 real questions about your docs and the expected answer in one line each.
Run them after every change. A good bot gets 8+ right and says "I don't know" for #10.

| # | Question | Expected answer (short) | Pass? |
|---|----------|-------------------------|-------|
| 1 | How do I install it? | `npm install …` | |
| 2 | Where do I set the API key? | `.env.local` → … | |
| 3 | … | … | |
| 10 | Something your docs do NOT cover | "I don't know" + suggestion | |
```


## Build instructions by tool

### Claude Code

Open a terminal in an empty folder, run `claude`, then paste the prompt.

```text
Build the "AI Chatbot for Your Docs (RAG)" app from the OwnlyPlans blueprint at https://wonly.dhfm.in/builder-4392ac/docs-chatbot-rag/.
Stack: AI SDK, Next.js, OpenAI, pgvector, Supabase.
Follow the plan's steps in order: Create the app and add the docs MCP → Create the vector database → Ingest your docs → Retrieval → Streaming chat route → Chat interface → Test with 10 real questions → Limits and deploy.
Download the full plan (Markdown) from the link above and keep it in the project root as PLAN.md.
Ask me before adding anything not in the plan. (Prepared for Claude Code.)
```

### Cursor

Open an empty folder in Cursor, start an Agent chat, then paste the prompt.

```text
Build the "AI Chatbot for Your Docs (RAG)" app from the OwnlyPlans blueprint at https://wonly.dhfm.in/builder-4392ac/docs-chatbot-rag/.
Stack: AI SDK, Next.js, OpenAI, pgvector, Supabase.
Follow the plan's steps in order: Create the app and add the docs MCP → Create the vector database → Ingest your docs → Retrieval → Streaming chat route → Chat interface → Test with 10 real questions → Limits and deploy.
Download the full plan (Markdown) from the link above and keep it in the project root as PLAN.md.
Ask me before adding anything not in the plan. (Prepared for Cursor.)
```

### Lovable

Start a new Lovable project and paste the prompt as your first message.

```text
Build the "AI Chatbot for Your Docs (RAG)" app from the OwnlyPlans blueprint at https://wonly.dhfm.in/builder-4392ac/docs-chatbot-rag/.
Stack: AI SDK, Next.js, OpenAI, pgvector, Supabase.
Follow the plan's steps in order: Create the app and add the docs MCP → Create the vector database → Ingest your docs → Retrieval → Streaming chat route → Chat interface → Test with 10 real questions → Limits and deploy.
Download the full plan (Markdown) from the link above and keep it in the project root as PLAN.md.
Ask me before adding anything not in the plan. (Prepared for Lovable.)
```

## Definition of done

- Every build step is complete and the app runs locally.
- The main user flow works end to end.
- Share your build on OwnlyPlans with a demo link, build time and tool.
