Getting Started
Overview
FastRAG is a production-ready RAG (Retrieval-Augmented Generation) starter kit built with Next.js, LangChain, Pinecone, Claude Haiku, and Voyage AI embeddings. It eliminates 40+ hours of boilerplate — vector ingestion pipelines, streaming responses, context window management, and a mobile-ready chat UI — so you can focus on building your actual product.
- Haiku 4.5Claude
- voyage-3.5Voyage AI
- ServerlessPinecone
- CheerioScraping
Getting Started
Prerequisites
You need Node.js and four service credentials (Anthropic, Voyage AI, Pinecone and Upstash Redis). All services have generous free tiers — you can run FastRAG at zero cost during development.
ANTHROPIC_API_KEYRequiredPowers Claude Haiku streaming chat. Get your key from console.anthropic.com — requires a payment method but Haiku is very affordable.
Get keyVOYAGEAI_API_KEYRequiredVoyage AI is Anthropic's recommended embeddings provider. voyage-3.5 gives you 200M free tokens — roughly 400,000 document pages at no cost.
Get keyPINECONE_API_KEYRequiredVector database for storing and querying embeddings. The free Starter plan supports 1 index and up to 100K vectors — sufficient for most projects.
Get key
Getting Started
Installation
- 1
Clone or unzip the project
If you have GitHub repo access (included with all purchases):
terminalgit clone fastrag.gitcd fastragOr unzip the downloaded ZIP file and open the folder in your terminal — both options are included with your purchase. - 2
Install dependencies
terminalnpm installSeeing peer dependency warnings? Runnpm install --legacy-peer-deps— common due to LangChain's rapid release cadence.
Getting Started
Environment Setup
Rename .env.example to .env.local and fill in your keys:
# Anthropic Claude — console.anthropic.comANTHROPIC_API_KEY=sk-ant-... # Voyage AI embeddings — dash.voyageai.comVOYAGEAI_API_KEY=pa-... # Pinecone vector DB — app.pinecone.ioPINECONE_API_KEY=pcsk_... # Must match the index name you create in Pinecone (case-sensitive)PINECONE_INDEX=fast-rag # Upstash Redis (demo rate limiting) — console.upstash.comUPSTASH_REDIS_REST_URL=https://...upstash.ioUPSTASH_REDIS_REST_TOKEN=...ANTHROPIC_API_KEYRequiredPowers Claude Haiku for streaming chat. Add a payment method at console.anthropic.com — Haiku costs fractions of a cent per message.
VOYAGEAI_API_KEYRequiredPowers voyage-3.5 embeddings for both ingestion and retrieval. First 200M tokens are free.
PINECONE_API_KEYRequiredUsed to upsert vectors during ingestion and query them during chat.
PINECONE_INDEXRequiredMust exactly match the index name in Pinecone — case-sensitive. "fast-rag" ≠ "Fast-RAG".
UPSTASH_REDIS_REST_URL / UPSTASH_REDIS_REST_TOKENRequiredCredentials for a free Upstash Redis database. The chat and ingestion routes use it to count demo usage per visitor IP (5 messages and 3 ingestions per 24 hours).
Getting Started
Pinecone Setup
- 1
Go to app.pinecone.io and sign in
- 2
Click "Create Index"
- 3
Use these exact settings:
- 4
Click Create — wait ~30 seconds for the index to initialise
Why 1024 dimensions?Voyage AI'svoyage-3.5model outputs 1024-dimensional vectors natively. This is the correct dimension — no forcing or truncation required. It also keeps Pinecone storage costs lower than 1536-dim alternatives.
Getting Started
Running Locally
npm run devOpen http://localhost:3000/chat in your browser.
How It Works
Architecture
FastRAG is a standard two-phase RAG pipeline. Ingestion happens once per document; retrieval and generation happen on every chat message.
Ingestion (once per document)
- 01SourcePDF / URL
- 02ParseExtract text
- 03Chunk1 000 chars
- 04Embedvoyage-3.5
- 05StorePinecone
Retrieval (every message)
- 01QuestionUser input
- 02Embedvoyage-3.5
- 03QueryTop-5 chunks
- 04PromptInject context
- 05StreamClaude Haiku
Four Next.js API routes handle everything:
pages/api/ingest-pdf.jsMultipart PDF upload, text extraction, chunking, Voyage AI embedding, Pinecone upsertpages/api/ingest-url.jsCheerio web scraping, content extraction, chunking, embedding, Pinecone upsertpages/api/chat.jsVoyage AI query embedding, Pinecone similarity search, Claude Haiku SSE streamingpages/api/demo-status.jsReturns current IP-based usage counters and reset timestamp for the demo UI
How It Works
PDF Ingestion
Handled by pages/api/ingest-pdf.js. Accepts a single PDF up to 20MB via multipart form upload.
- 1
Upload Parsing Formidable handles the multipart upload and writes the file to a temp path on the server filesystem.
- 2
Text Extraction
pdf-parsereads the buffer and extracts all raw text, page by page. - 3
Chunking
RecursiveCharacterTextSplittercuts text into 1000-character chunks with 200-character overlap. Overlap preserves sentence context across chunk boundaries. - 4
Embedding
embedBatch()sends all chunks to Voyage AI voyage-3.5 withinputType: "document". LangChain handles batch splitting automatically. - 5
Storage Vectors are upserted to Pinecone under the specified namespace (default:
demo). Each vector carries source filename andchunkIndexas metadata. - 6
Cleanup The temp file is deleted from disk immediately after processing. Returns
{ chunksIngested, totalCharacters, source }to the frontend.
How It Works
URL Ingestion
Handled by pages/api/ingest-url.js. No headless browser required — Cheerio runs natively in Node.js with zero ESM conflicts on Vercel.
- 1
Fetch A standard
fetch()call with a 15-second timeout retrieves the raw HTML. User-Agent is set to avoid basic bot blocking. - 2
Parse & Clean Cheerio loads the HTML and removes script, style, nav, footer, header, noscript, and iframe elements.
- 3
Semantic Targeting Content is extracted preferentially from
<main>,<article>, or[role="main"]before falling back to<body>— ensuring clean signal over boilerplate. - 4
Text Normalisation Whitespace is collapsed, excessive newlines are trimmed, and the result is validated for minimum length (50 chars).
- 5
Chunk → Embed → Store The same chunking → Voyage AI embedding → Pinecone upsert pipeline as PDF ingestion. Source URL is stored as metadata for citations.
How It Works
Chat & Retrieval
Handled by pages/api/chat.js. Every user message triggers a full retrieval cycle before Claude is called.
- 1
Rate Limit Check IP is extracted from
x-forwarded-forheaders.incrementUsage()checks and increments the message counter — returns429withresetAtif over limit. - 2
Query Embedding The user's message is embedded using Voyage AI voyage-3.5 with
inputType: "query"— a separate embedder instance optimised for asymmetric retrieval. - 3
Source Scoping Every ingested file or URL is recorded with its type. If the question says "the document" or "the URL" (or names a source such as
handbook.pdf), only that source is searched — the most recent one for singular wording, all of them for plural. Summary-style questions sample chunks evenly across the source. - 4
Pinecone Query Top-5 matching chunks are retrieved via similarity search. For unscoped questions, matches below a 0.3 cosine score threshold are filtered out.
- 5
First SSE Event Before streaming begins, a JSON event is written containing
sources[],hasContextflag, thescopethe answer was restricted to, and current usage counters — so the UI can render citations and update meters immediately. - 6
System Prompt Retrieved chunks are joined and injected into Claude's system prompt inside
<context>tags. If no chunks pass the threshold, Claude is instructed to say so rather than hallucinate. - 7
Claude Haiku Stream
anthropic.messages.stream()streams response deltas as SSEtext_deltaevents. The final event carriesdone: trueand token usage stats.
How It Works
Frontend
The demo UI lives in pages/chat.js with components in components/chat/. A two-column layout: left panel for ingestion, right panel for chat. See it running at /chat.
DemoUploaderHandles PDF drag-and-drop and URL input. Calls /api/ingest-pdf and /api/ingest-url. Shows real chunk stats on success.
ChatPanelSSE stream consumer. Renders token deltas in real time, shows source cards on first event, auto-scrolls.
UsageMeterLive progress bars for messages and ingestions. Amber at 70%, full lock wall with upgrade CTA at 100%.
SourceCardDisplays retrieved source filename/URL with animated relevance score bar. Rendered before answer text begins.
Deployment
Deploy to Vercel
FastRAG is optimised for Vercel. No special configuration needed — deployment takes about 5 minutes.
- 1
Push your code to GitHub
terminalgit init && git add .git commit -m "initial"git remote add origin https://github.com/you/fastrag.gitgit push -u origin main - 2
Import to Vercel
Go to vercel.com/new, import your GitHub repo, and select Next.js as the framework preset.
- 3
Add environment variables
In Vercel project → Settings → Environment Variables, add all of these keys:
ANTHROPIC_API_KEYVOYAGEAI_API_KEYPINECONE_API_KEYPINECONE_INDEXUPSTASH_REDIS_REST_URLUPSTASH_REDIS_REST_TOKEN
- 4
Click Deploy — live in ~2 minutes
Cheerio-based scraping runs in Vercel's standard Node.js runtime with no special configuration. No Puppeteer layer, no external browser service, no cold-start penalties.Vercel's free Hobby plan has a 10-second function timeout. Very large PDFs may hit this limit. Upgrade to Pro ($20/mo) for a 60-second limit, or chunk large files before upload.
Reference
Troubleshooting
Click any error to expand the cause and fix.
- Cause
- Your Pinecone index was created with 1536 dimensions (the OpenAI default) instead of 1024, which voyage-3.5 outputs natively.
- Fix
- Delete the index in the Pinecone dashboard and recreate it with Dimensions: 1024, Metric: Cosine. See Pinecone Setup above.
- Cause
- The
PINECONE_INDEXvalue in your.env.localdoesn't exactly match the index name in your Pinecone dashboard. - Fix
- Open
.env.localand verify spelling and casing match exactly. "fast-rag" ≠ "Fast-RAG" ≠ "fastrag".
- Cause
- The IP-based rate limiter has hit 5 messages or 3 ingestions for this IP in the current 24-hour window.
- Fix
- Wait for the session to reset (shown in the UI countdown). In development you can also delete the
demo:<ip>:messagesanddemo:<ip>:ingestionskeys from your Upstash Redis database to reset immediately.
- Cause
- The page may load content via client-side JavaScript after initial HTML delivery (SPAs, dynamic dashboards), which Cheerio cannot execute.
- Fix
- Try a different URL — public documentation sites, blogs, and marketing pages work best. Pages that require JS execution or login will not scrape correctly.
- Cause
- A dependency is shipping ESM-only code that conflicts with Next.js Pages Router's CommonJS bundler on Vercel.
- Fix
- FastRAG uses Cheerio which is fully CJS-compatible. If you see this error, check for any manually added ESM-only packages and replace them with CJS equivalents.
- Cause
- Peer dependency conflict between LangChain sub-packages, which update very frequently.
- Fix
- Run:
npm install --legacy-peer-deps— resolves most conflicts without breaking functionality.
- Cause
- The
ANTHROPIC_API_KEYis missing, malformed, or the key was created for a different Anthropic organization. - Fix
- Copy the key directly from console.anthropic.com/settings/api-keys — ensure no extra whitespace. Add a payment method if the account is new.
- Cause
- The
VOYAGEAI_API_KEYis missing or incorrect. - Fix
- Copy the key from dash.voyageai.com. Keys start with
pa-. VerifyVOYAGEAI_API_KEYis set in both.env.local(local) and Vercel environment variables (production).
Reference
FAQ
No. The free Starter plan supports 1 index and up to 100K vectors — plenty for development and small production projects.
Yes. Chat logic is isolated in lib/claude.js. Swap the model string to claude-opus-4-6, claude-sonnet-4-6, or any other Anthropic model. The streaming interface stays identical.
Yes. Embedding logic is isolated in lib/embeddings.js. Replace VoyageEmbeddingswith any LangChain-compatible embeddings class. Just make sure your Pinecone index dimension matches the new model's output.
Yes. MIT license. Build and sell products on top of FastRAG, charge clients, and keep all revenue. The only restriction is reselling the source code itself.
Currently PDF and any public URL. Extend ingest-pdf.jswith LangChain's other document loaders to add .txt, .docx, .md, .csv, or HTML files.
In the Pinecone dashboard → your index → Namespaces → delete the 'demo' namespace. This removes all vectors without deleting the index itself. Or delete the entire namespace via the Pinecone SDK.
Each visitor IP gets 5 chat messages and 3 ingestions per 24 hours. Counters live in Upstash Redis (lib/demo-limits.js) with a 24-hour expiry, so they reset automatically. Delete the demo:<ip>:messages and demo:<ip>:ingestions keys in your Upstash database to reset one visitor during development.
Yes. All buyers get lifetime access to the private GitHub repository. Simply git pull to get the latest — no re-purchase required.