Skip to content

Rapitzo/studio-knowledge-chat

Repository files navigation

studio-knowledge-chat

What this is

A small RAG demo: a chat assistant that answers questions from a markdown corpus the studio owns, with [1]-style citations that deep-link to the exact paragraph in the source document. There is no client data in the repo. The corpus under corpus/ is the studio's own handbook (services, pricing, FAQ, onboarding, security, stack), MIT-licensed alongside the code.

The demo runs end-to-end on a fresh laptop with no API keys and no external services. Set OPENAI_API_KEY later to swap the templated mock answers for real model output.

Quickstart

git clone https://github.com/Rapitzo/studio-knowledge-chat.git
cd studio-knowledge-chat
npm install
npm run ingest
npm run dev

Open http://localhost:3000, click through /dev-login, pick a user, and ask the chat a question. Citations link to /sources/<slug>#<anchor> and scroll the right section into view.

No .env.local is required for a first run. Defaults take over: dev login, mock-mode AI, JSON-on-disk index. Copy .env.example to .env.local only when you want to switch on a real provider or magic-link auth.

Env vars

Name Required? What it enables
AUTH_MODE optional (dev) dev (default) uses /dev-login cookie. magic-link uses NextAuth + SMTP.
OPENAI_API_KEY optional Real AI answers + real embeddings. If unset, the app boots in mock mode.
ANTHROPIC_API_KEY optional Use Claude for chat (set AI_PROVIDER=anthropic).
XAI_API_KEY optional Use Grok for chat (set AI_PROVIDER=xai).
VOYAGE_API_KEY optional Use Voyage for embeddings (set EMBEDDINGS_PROVIDER=voyage).
AI_PROVIDER optional openai | anthropic | xai | ollama | lmstudio | claude-code.
EMBEDDINGS_PROVIDER optional openai | ollama | voyage.
OLLAMA_BASE_URL optional Use a local Ollama for chat or embeddings (no key required).
LMSTUDIO_BASE_URL optional Use LM Studio locally (no key required).
CLAUDE_CODE_BIN optional Use the Claude Code CLI as the chat provider.
INDEX_PATH optional Override the JSON vector-store path (default data/index.json).
CORPUS_DIR optional Override the markdown corpus path (default corpus).
DATABASE_URL only for magic-link Postgres URL. Required when AUTH_MODE=magic-link.
EMAIL_SERVER only for magic-link Nodemailer SMTP URL. Required when AUTH_MODE=magic-link.
EMAIL_FROM only for magic-link Verified sender address. Required when AUTH_MODE=magic-link.
NEXTAUTH_URL only for magic-link Public base URL.
NEXTAUTH_SECRET only for magic-link NextAuth signing secret. openssl rand -base64 32.
DEMO_ALLOWLIST only for magic-link Comma-separated emails. Empty = anyone with a valid magic link.

Login in local mode

Default AUTH_MODE=dev:

  1. Go to http://localhost:3000/dev-login (or click the sign-in link from /).
  2. Pick one of three pre-seeded users — alice@example.local, bob@example.local, or studio@example.local.
  3. A dev-session cookie is set in your browser. The cookie expires after 24 hours. Sign out with the button in the chat header.

No email is sent, no DB row is written, nothing leaves your laptop.

To switch on the production magic-link flow, set AUTH_MODE=magic-link in .env.local plus the DATABASE_URL, EMAIL_SERVER, EMAIL_FROM, NEXTAUTH_URL, and NEXTAUTH_SECRET env vars. Visit /login instead of /dev-login. The magic-link code path stays committed; nothing was deleted.

Local services

None required. The retrieval index is a JSON file on disk (data/index.json), loaded into memory at server start. npm run ingest walks corpus/*.md, chunks each file at ~600 tokens with 80 tokens of overlap, embeds each chunk, and writes the index file. In mock mode (no AI key set) the embedding is a deterministic local hash, so identical input always lands at the same vector and the kNN search still works.

Re-skin guide

  1. Replace the markdown under corpus/ with your own files. One file per logical document. The filename (sans .md) becomes the slug used in citation links.
  2. npm run ingest — re-embeds only the chunks whose content hash changed.
  3. Restart npm run dev. The chat picks up the new corpus immediately.

If you want a tighter sign-in gate in magic-link mode, set DEMO_ALLOWLIST to a comma-separated list of approved emails.

Architecture

  • Retrieval. scripts/ingest.ts chunks corpus/*.md into ~600-token windows with 80-token overlap, embeds each chunk with the configured provider (or a deterministic local hash in mock mode), and writes data/index.json. The store keeps documents, chunks, and embeddings in a single JSON file.
  • Chat. app/api/chat/route.ts embeds the user's question, runs cosine kNN over the JSON store (top 6 chunks), and either streams a real model answer (when a key is set) or returns a templated mock answer that still cites the retrieved chunks. The first line of the response is a JSON payload with citation metadata; the rest is the assistant text.
  • Citations. lib/citations.ts parses [n] markers in the assistant output and turns each into a link to /sources/<slug>#<anchor>. The source page renders the markdown with anchored sections so the link lands on the right paragraph.

Licence

MIT. See LICENSE. The corpus under corpus/ is also MIT and is studio-owned content. There is no client data in this repo.

About

RAG chat over a markdown corpus with citation deep-links to source paragraphs. Next.js 14 + pgvector + magic-link.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors