Skip to content

01. Product and System Overview

What the product does

Browser RAG is a private, fully local RAG workbench in the browser. Users create projects, upload documents, index them with a local embedding model, and ask questions answered by a local LLM with citations. Document bytes and vectors stay on the device; the only expected network use is downloading model weights.

Evidence: README.md, AGENTS.md (“must be able to be run on browser client side entirely”).

Primary users and workflows

User Workflow
Privacy-conscious knowledge worker Index personal PDFs/notes; ask questions without a cloud RAG API
ML/web engineer Experiment with local embeddings, hybrid search, and small on-device LLMs
Demo / portfolio visitor Use the GitHub Pages build at /browser-rag/

Core workflows

  1. Create project — choose embedding model, chunk size/overlap, hybrid/top-K (src/routes/projects.tsx, src/lib/projects.ts)
  2. Upload & index — extract → chunk → embed → store (src/routes/documents.tsxindexDocument)
  3. Load models — embedding + LLM into memory (SystemInitProvider, chat page)
  4. Ask — rewrite (if multi-turn) → hybrid retrieve → stream answer + citations (generateRAGAnswer)
  5. Inspect — retrieval debug panel, chunk explorer, history, settings diagnostics
  6. Backup — export/import PGlite data dir as .tar.gz

Major subsystems

Subsystem Responsibility Entry
UI shell Navigation, theme, project switcher src/components/layout/*
System init Prefs, active project, LLM/embedding load src/context/system-init-context.tsx
RAG Index, retrieve, orchestrate answers src/rag/*
LLM Multi-engine load/stream/parse src/llm/*, src/hooks/use-*
Persistence PGlite schema + file IDB src/db/*, src/lib/document-files.ts
Workers Off-thread extract/chunk/embed src/workers/*

High-level architecture

graph TD
  classDef default fill:#1e293b,stroke:#38bdf8,stroke-width:2px,color:#f8fafc
  classDef highlight fill:#065f46,stroke:#34d399,stroke-width:2px,color:#f0fdf4
  classDef warning fill:#78350f,stroke:#fbbf24,stroke-width:2px,color:#fffbeb

  Browser["Browser SPA<br/>Vite + React 19"]:::highlight
  Pages["GitHub Pages<br/>static dist/"]
  IDB1["IndexedDB<br/>PGlite data dir"]
  IDB2["IndexedDB<br/>browser-rag-files"]
  LS["localStorage<br/>preferences"]
  CDN["Weight CDNs<br/>HF / MLC"]:::warning

  Pages --> Browser
  Browser --> IDB1
  Browser --> IDB2
  Browser --> LS
  Browser -.-> CDN

  linkStyle default stroke:#64748b,stroke-width:2px

There is no application backend. Deployment is a static asset host. Persistence is browser storage; model weights may be fetched and cached by the ML libraries.

Primary ask-flow sequence

%%{init: {
  "theme": "base",
  "themeVariables": {
    "primaryColor": "#1e293b",
    "primaryTextColor": "#f8fafc",
    "primaryBorderColor": "#38bdf8",
    "lineColor": "#64748b",
    "actorBackground": "#1e293b",
    "actorBorder": "#38bdf8",
    "actorTextColor": "#f8fafc",
    "labelBoxBorderColor": "#38bdf8",
    "labelBoxBkgColor": "#1e293b",
    "labelTextColor": "#f8fafc",
    "noteBorderColor": "#fbbf24",
    "noteBkgColor": "#78350f",
    "noteTextColor": "#fffbeb"
  }
}}%%
sequenceDiagram
  actor User
  participant Chat as Chat Route
  participant Orch as generateRAGAnswer
  participant LLM as LLM Runtime
  participant Ret as retrieveChunks
  participant Emb as Embedding Worker
  participant DB as PGlite

  User->>Chat: Submit question
  Chat->>Orch: query + history + handles
  alt history present
    Orch->>LLM: rewriteQueryForRetrieval
    LLM-->>Orch: standalone search query
  end
  Orch->>Ret: retrievalQuery
  Ret->>Emb: embedQuery
  Emb-->>Ret: query vector
  Ret->>DB: vector <=> + keyword tsquery
  Ret-->>Orch: fused citations + debug
  Orch->>LLM: stream answer with context
  LLM-->>Chat: text_delta / thinking_delta
  Chat-->>User: Markdown answer + citations

Key technical bets and tradeoffs

Bet Upside Tradeoff
Everything in-browser Privacy, no server cost, offline-capable after weights cached Device memory/GPU limits; large downloads
Real Postgres (PGlite) + SQL hybrid search Familiar SQL, GIN FTS, pgvector ops WASM DB size; no ANN index yet → scan cost grows
Multi-engine LLM adapter Portability across WebLLM / Transformers / custom kernels Complexity; uneven feature support
Soft project embedding lock Consistency for vectors Can still change model via update path; mixed dims risk if misused
Static Pages deploy Simple CI Harder to set COOP/COEP / caching policy

Interview soundbite — “What did you build?”

Browser RAG is a fully client-side RAG system: PGlite with pgvector in IndexedDB, Transformers.js embeddings in a Web Worker, hybrid vector+keyword search fused with RRF, and a multi-engine local LLM runtime that streams answers with citations and a retrieval debug panel — all without an application server.