Deep dive

Everything included.
Nothing hidden.

No black boxes. No magic abstractions. Every feature is yours to read, customize, and extend. Here's exactly how each one works.

Web Scraping

Web Scraping Engine

Turn any URL into searchable knowledge in seconds.

FastRAG's scraping pipeline fetches any public URL and strips it down to pure signal — no nav menus, no cookie banners, no boilerplate. It intelligently targets semantic content zones like <main> and <article> before falling back to the full page body. The extracted text is chunked with LangChain's RecursiveCharacterTextSplitter and stored in Pinecone under an isolated namespace, ready for retrieval. The whole pipeline runs serverlessly on Vercel with zero ESM conflicts.
  • Fully compatible with Vercel serverless — zero ESM issues
  • Targets semantic content zones before falling back to body
  • Strips nav, footers, scripts, and boilerplate automatically
  • Configurable chunk size (1000 tokens) and overlap (200 tokens)
  • 15-second timeout with graceful error handling
scraping.js
500)">// pages/api/ingest-url.js
async function scrapeUrl(url) {
500)">// → fetch → parse → strip boilerplate
500)">// → target
/
first
500)">// → chunk with RecursiveCharacterTextSplitter
500)">// → upsert to Pinecone namespace
}

Full source included in the starter kit

Get the code
PDF Ingestion

PDF Ingestion Pipeline

Drag, drop, and start chatting with any document.

The PDF pipeline accepts multipart form uploads up to 20MB. Files are parsed for full text extraction, chunked, embedded, and stored in Pinecone — every chunk tagged with its source filename so the chat interface can cite exactly which document an answer came from. Temp files are deleted from disk immediately after processing. Ingestion statistics (chunks created, characters processed) are returned to the frontend so users get immediate confirmation of what was indexed.
  • Multipart upload — no base64 encoding overhead
  • Full text extraction from any standard PDF
  • Per-chunk source metadata for accurate citations
  • Temp files cleaned up immediately after processing
  • Returns chunk count and character stats on completion
pdf.js
500)">// pages/api/ingest-pdf.js
export default async function handler(req, res) {
500)">// → parse multipart upload (up to 20MB)
500)">// → extract text from PDF buffer
500)">// → chunk → embed in batch → upsert
500)">// → return { chunksIngested, totalCharacters }
}

Full source included in the starter kit

Get the code
Voyage AI Embeddings

Voyage AI Embeddings

Anthropic's recommended embeddings — 200M free tokens to start.

FastRAG uses Voyage AI's voyage-3.5 model — the embeddings provider officially recommended by Anthropic. The first 200 million tokens are free, covering roughly 400,000 document pages before you pay anything. Separate embedding instances are used for documents and queries, optimising the vector space for asymmetric retrieval — the pattern where short questions retrieve long passages. LangChain handles batch splitting automatically.
  • voyage-3.5 — Anthropic's recommended embedding model
  • 200M free tokens — ~400,000 document pages at no cost
  • Separate document vs. query embedders for asymmetric retrieval
  • LangChain handles batch splitting automatically
  • Singleton instances prevent cold-start overhead per request
embeddings.js
500)">// lib/embeddings.js
500)">// Separate instances for document ingestion
500)">// and query retrieval — optimised vector space
500)">// for asymmetric search (short query → long doc)
export const embedBatch = (texts) => { ... }
export const embedQuery = (query) => { ... }

Full source included in the starter kit

Get the code
Streaming

Real-Time Claude Streaming

Answers appear word by word, grounded in your documents.

FastRAG streams responses using claude-haiku-4-5 — Anthropic's fastest Claude model — chosen for demo latency: first token arrives in under a second even on cold starts. The first SSE event carries source citations and a usage payload before any answer text, so the UI renders source cards and updates the usage meter without a separate API call. If no chunks score above the relevance threshold, Claude says so — graceful degradation over confident fabrication.
  • claude-haiku-4-5 — fastest Claude model, sub-second TTFT
  • First SSE event carries sources + usage in one payload
  • Retrieved context injected into system prompt via <context> tags
  • 0.3 cosine similarity threshold filters irrelevant chunks
  • Usage meter stays in sync without a separate status call
streaming.js
500)">// lib/claude.js
500)">// → anthropic.messages.stream() with RAG system prompt
500)">// → first event: sources + usage metadata
500)">// → token deltas streamed as SSE
500)">// → final event: done flag + token usage stats

Full source included in the starter kit

Get the code
Demo Rate Limiting

IP-Based Demo Rate Limiting

Let visitors experience the product — without burning your API budget.

FastRAG ships with a production-ready IP-based rate limiter built for public demo pages. Each visitor gets 5 chat messages and 3 ingestions per 24-hour window before being nudged toward sign-up. Limits are tracked in a lightweight JSON file store — no Redis, no database required. The API returns structured 429 responses with a resetAt timestamp so the UI can show an exact countdown. Usage meters, amber warnings at 70%, and a full upgrade CTA wall are all included.
  • 5 chat messages + 3 ingestions per visitor per 24h
  • File-based session store — no Redis or DB required
  • Correct x-forwarded-for parsing for Vercel's proxy chain
  • 429 responses include resetAt timestamp for countdown UI
  • Live usage meters with amber warnings and upgrade CTA wall
ratelimiting.js
500)">// lib/demo-limits.js
export function incrementUsage(ip, field) {
500)">// → read session from JSON store
500)">// → auto-reset if 24h window elapsed
500)">// → throw { limitReached, resetAt } if over limit
500)">// → increment + persist, return session
}

Full source included in the starter kit

Get the code
Namespace Isolation

Pinecone Namespace Isolation

Multi-tenant vector storage with zero cross-contamination.

Every ingestion and retrieval operation is scoped to a Pinecone namespace. In the demo, all visitors share the "demo" namespace. In production, swap it for a userId or orgId — each tenant's documents stay completely isolated within a single Pinecone index, with no schema migration or provisioning step. The namespace flows as a single string through the entire pipeline: ingest API → vector store → chat retrieval. One index, unlimited tenants, zero extra cost.
  • One Pinecone index, unlimited namespaces — no added cost
  • Namespaces auto-created on first document upsert
  • Zero cross-contamination between tenants by design
  • Namespace flows through ingest → store → retrieval uniformly
  • Swap "demo" for userId/orgId for instant multi-tenancy
namespaces.js
500)">// lib/vector-store.js
500)">// upsertVectors(vectors, namespace)
500)">// → index.namespace(namespace).upsert(vectors)
500)">// querySimilar(embedding, topK, namespace)
500)">// → index.namespace(namespace).query(...)
500)">// → each tenant's vectors are fully isolated

Full source included in the starter kit

Get the code

Ready to ship?

Get the full source code and start building your AI SaaS today.