Readstacks
Private local RAG document assistant — per-user isolated vector search, multi-provider fallback, JWT-secured, streaming chat. Live now.
Verified live 2026-09-13 (HTTP 200 on readstacks.duckdns.org, Nginx → 127.0.0.1:3000, PM2). 10/10 tests green via npm test. Formats: PDF, DOCX, TXT, MD, XLS, XLSX, CSV.
01 — Problem
RAG demos either ship your documents to a third-party SaaS or trap you on a single cloud vendor — and die entirely when that one provider has an outage. Neither is acceptable for private documents.
02 — Solution & Architecture
Local-first, multi-tenant RAG. Files are parsed, paragraph-aware chunked, embedded and written into the user's own vector index; chat streams over SSE with mid-stream provider failover; one docker compose up -d brings backend + local Ollama online.
Browser (React 19 + Vite, Tailwind, Radix) ──SSE──▶ Express API
routes: auth.js · chat.js · documents.js
services: aiService.js · rateLimiter.js · providers/{gemini,groq,nvidia,ollama}
retrieval: MiniSearch BM25 + Vectra cosine, fused at query time
storage: SQLite + Vectra, namespaced per user · transactional uploads
ops: docker compose (backend + ollama/ollama) · Nginx (SSE-safe) · PM203 — Engineering challenges
How is per-user isolation guaranteed?
Databases and vector indexes are namespaced per user on the host they own; transactional uploads commit files, metadata rows and vector entries atomically — a failure rolls everything back, never orphaned chunks.
What happens when a provider dies mid-answer?
Token-bucket rate limiting (Gemini 15/min, Groq 30/min, NVIDIA 30/min, Ollama unlimited) triggers instant fallback; if a provider dies mid-SSE-stream, the backend re-opens against the next provider and the UI keeps rendering tokens.
How do answers stay grounded?
Chunks respect paragraph boundaries; PDF ingest extracts page numbers so responses carry citations like [doc.pdf p.7] next to grounded claims.
04 — Security
- JWT in HttpOnly SameSite Secure cookies — no tokens in localStorage
- bcrypt hashing, signup password policy, express-rate-limit on auth endpoints
- Per-user filesystem isolation + transactional uploads
05 — Testing
- 10/10 passing (chunking + fallback suites) — run:
npm test - CI via GitHub Actions; Docker-ready; Swagger-documented API
06 — Result & demo
Privacy by default, resilient AI, zero-friction ops — and it's running right now. Open the demo, upload a document, and watch streamed, cited answers.