Project
DocuMind
Semantic document intelligence for PDFs.
What it does
DocuMind turns a static PDF into a searchable, queryable knowledge source:
- Secure document management — every document record and chunk is owned by a user and every read/write is filtered by the authenticated user id.
- PDF ingestion — uploads are validated (PDF only, non-empty, ≤ 10 MB) and parsed server-side.
- Text extraction — text is extracted per page so page boundaries are preserved.
- Document chunking — page text is normalized and split into overlapping, page-aware chunks.
- Semantic search / retrieval — each chunk is embedded into a dense vector; a query is embedded the same way and ranked against the document's chunks using cosine similarity.
- Evidence-backed document Q&A — only the retrieved excerpts are supplied to the answer step, and the response cites the supporting chunks.
- Source / page references — citations returned to the client carry the chunk id and the page range the evidence came from.
How it works
- PDF upload —
POST /api/documentsaccepts amultipart/form-dataupload. The file is rejected unless it is a non-empty PDF no larger than 10 MB. - Text extraction — the PDF buffer is parsed page by page, and the text items of each page are concatenated. Pages without extractable text produce an explicit ingestion error.
- Page-aware chunking — each page's text is whitespace-normalized and split into chunks of up to 1200 characters with a 200-character overlap, so a chunk never spans pages and page numbers remain accurate.
- Semantic embeddings — every chunk is embedded into a dense float vector. Embeddings are generated with bounded concurrency so ingestion stays within provider rate limits.
- MongoDB storage — chunks (with their vectors) and the document metadata are persisted,
each tied to the owning
userId.
Features
- Area: Capability
- Authentication: Email + password accounts, bcrypt password hashing, signed JWT session in an HttpOnly cookie, server-side session lookup, logout
- Document management: Upload, list, open, rename, and delete documents; per-user chunk counts
- PDF pipeline: Real PDF text extraction with page awareness, overlapping chunking, batch embedding generation
- Retrieval: Query embedding, cosine similarity ranking, configurable
topK, minimum similarity threshold - Grounded answers: Responses constrained to retrieved excerpts, citation validation, explicit "not enough evidence" answer
- Chunk browsing: Inspect stored chunks per document without exposing embedding vectors
- Ownership enforcement: All document, chunk, and RAG queries are scoped by
userId - UI: Responsive dashboard, workspace, and settings screens built on the existing Stitch design system
Technology
- Layer: Technology
- Framework: Next.js 15 (App Router, Route Handlers, Server Actions-less API routes)
- Language: TypeScript 5.9 (strict mode)
- UI: React 19, Tailwind CSS 4,
motion,lucide-react,class-variance-authority - Database: MongoDB with Mongoose 9 (cached global connection pool)
- Auth:
jsonwebtoken(HS256 JWT) +bcryptjspassword hashing - Document processing:
pdf-parsefor page-level text extraction - Embeddings / generation: Server-side calls to a managed embedding + text generation API (keyed by
GEMINI_API_KEY) - Testing: Vitest
- Linting: ESLint with
eslint-config-next - Hosting: Vercel (serverless) with MongoDB Atlas
Honest scope
- Synchronous ingestion. Uploads are parsed and embedded inside the request, so very large PDFs can take a while or approach serverless execution time limits. There is no background job queue yet.
- In-application vector ranking. Retrieval loads the document's chunks and ranks them with cosine similarity in application code rather than using a MongoDB Atlas Vector Search index, which is simpler and exact but does not scale to very large corpora.
- PDF text dependency. The pipeline needs a real text layer. Scanned or image-only PDFs without OCR produce no extractable text and are rejected.