Skip to content

Repository files navigation

doc-chat

Chat with your own documents. Upload a PDF, paste text, or point it at a URL, and ask questions. Every answer cites the chunks it came from, and the model is told to say so rather than invent when the sources do not cover the question.

RAG over pgvector, end to end, in about 400 lines.

What it does

  1. Ingest. Extract text from a PDF, a pasted block, or a scraped web page.
  2. Chunk. Split on paragraph boundaries with overlap, dropping fragments.
  3. Embed. Voyage voyage-3, batched, with the document input type.
  4. Store. Postgres with pgvector, through Supabase.
  5. Ask. Embed the question with the query input type, pull the nearest chunks, and stream an answer grounded in them.

Both the ingest and the chat endpoints stream NDJSON, so the UI shows progress during a long embed and renders citations before the first token of the answer arrives.

Stack

Piece Choice
Framework Next.js 16, App Router, node runtime
Embeddings Voyage voyage-3
Vector store Supabase Postgres with pgvector
Answering Anthropic claude-haiku-4-5
PDF extraction unpdf
Styling Tailwind 4

Setup

npm install
npm run dev

You need four environment variables:

Variable For
VOYAGE_API_KEY Embeddings
ANTHROPIC_API_KEY Answering
SUPABASE_URL Vector store
SUPABASE_ANON_KEY Vector store

The database needs two tables and one RPC before anything works. The schema is in TECHNICAL.md, including the match_chunks function the search path calls.

Layout

app/api/ingest/route.ts   extract, chunk, embed, store; streams progress
app/api/chat/route.ts     retrieve, then stream a grounded answer
app/page.tsx              the whole UI
lib/chunker.ts            paragraph-first splitting with overlap
lib/embed.ts              Voyage client, document and query modes
lib/store.ts              Supabase reads and writes
lib/types.ts              shared shapes, including the stream event union

How it works

TECHNICAL.md covers the chunking strategy and why it cascades through three boundary types, why the document and query embedding calls are separate functions, the database schema and the match_chunks RPC, the NDJSON streaming protocol, and the known limits of the URL scraper.

About

Chat with your own documents. Upload a PDF, text, or URL and get answers with citations. RAG over pgvector.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages