Benny Duah
Back to Work
1 min read
Automation & AI
Documentation

Anchor

Next.js
AWS Textract
Google Gemini
Supabase
pgvector
Microsoft Entra ID
Key Impact3sAverage response time
Cover image for Anchor
Project Overview

Get direct answers with page citations from 500-page PDFs in seconds instead of skimming for hours.

What it is

I built Anchor as an intelligent document search tool that reads complex PDFs and answers questions about them. You upload a manual or policy guide and ask a question in plain English. Anchor returns a verified answer with the exact source page number.

What it does

  • Find exact answers in seconds across hundreds of pages without manual skimming.
  • Verify every claim with direct page citations linked to the original document text.
  • Ask questions naturally without needing technical keywords or exact phrasing.
  • Prevent guesswork by relying only on confirmed text inside your uploaded file.

How it works

When you upload a PDF, Anchor sends it to an automated text reader (optical character recognition, or OCR) to extract every word. The app slices the text into short paragraphs and converts each one into a list of numbers (an embedding) to capture its meaning. Anchor saves these numbered paragraphs in a searchable database.

When you ask a question, an AI triage assistant checks your intent first. Simple greetings get an immediate reply, while real inquiries get converted into an optimized search query. The database matches the math of your question against stored paragraphs. An AI assistant then reads the best matches and writes a concise answer with citation tags.

Visual search and citation flow

Why it matters

Teams waste hours searching dense handbooks for single policy rules. Anchor returns precise answers with verified page numbers in under three seconds, removing manual lookups and eliminating hallucinated answers.

View the code on GitHub →

Technical Documentation

Architecture / System design

Anchor isolates workloads across dedicated cloud services: Next.js and Microsoft Entra ID handle authentication and routing, AWS S3 and Textract run asynchronous OCR ingestion, Supabase pgvector manages vector storage and cosine search, and Google Gemini powers 768-dimension embeddings and agentic response generation.

Implementation details

  1. Ingestion & Indexing: S3 PDF uploads trigger asynchronous AWS Textract OCR (status: processing). The backend polls completion, chunks text into 500-token blocks (50-token overlap), generates 768-dim Gemini embeddings (text-embedding-004), and stores vectors in Supabase pgvector (status: ready).
  2. Agentic Retrieval & Grounding: Gemini 1.5 Flash evaluates user queries. Informational searches generate 768-dim vectors to retrieve top-5 chunks via cosine similarity, synthesize answers with bracketed page citations ([1]), and retry up to twice with rewritten queries if context is missing.
  3. Two-Tier Rate Limit Defense: Server-side IP rate limiting checks client request velocity before querying Google Gemini, shielding upstream quotas from abuse. If upstream quotas are reached, custom Next.js error handlers catch HTTP 429 exceptions and render clear user-facing retry prompts rather than generic 500 crashes.

Why this approach?

  • Chose 768-dimension embeddings over 3,072 dimensions because Supabase pgvector caps vector columns at 2,000 dimensions — the tradeoff was losing minor theoretical precision for fast HNSW indexing.
  • Chose a multi-cloud split (AWS Textract + Google Gemini) over an all-AWS stack because AWS Bedrock rate limits throttled new accounts — the tradeoff was managing dual cloud credentials to prevent upload stalls.
  • Chose front-door agent triage over direct vector search because non-informational queries wasted database calls — the tradeoff was ~200ms initial latency to gain automated query rewriting and search retries.
  • Chose server-side IP rate limiting and error interception over unthrottled proxying because rapid agentic multi-requests exhausted free-tier provider limits in production — the tradeoff was tracking client IP counters to preserve uptime and prevent 500 errors.

Known limitations

  • Upstream Free-Tier Quota: While local IP rate limiting and 429 interception prevent crashes and bot exhaustion, high aggregate traffic across all users remains bounded by provider-level limits.
  • Document-Scoped Search: Retrieval targets active documents rather than organization-wide workspaces.

Future work

  • Replace background polling with SQS / webhook event notifications for OCR completion.
  • Support multi-document workspace search.
Next.js
TypeScript
Microsoft Entra ID
AWS S3
AWS Textract
Supabase (pgvector)
Google Gemini API
Found this technical breakdown useful?Share it with your team or network.