Skip to content

About

Self-hosted OCR document archive: PaddleOCR turns scanned pages into searchable, structured text locally — no external OCR API — with Backblaze B2 (S3-compatible) as the single source of truth and a rebuildable SQLite index for keyword search.

Topics

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

PaddleOCR Document Archive

Turn a pile of scanned pages into a searchable, structured archive — without sending a single page to an external OCR API. Raw scans land in Backblaze B2, PaddleOCR runs locally over each page (text detection → angle classification → recognition), and three derived artifacts are written back to B2 per page: a structured result.json (boxes + text + confidence), a rendered overlay.png for visual QA, and a searchable text.txt. A lightweight SQLite index — rebuildable entirely from those B2-resident artifacts — powers keyword search. B2 is the single source of truth; the only credential you need is a B2 key.

Built for archivists, legal teams, and digital-preservation workflows that need on-device OCR over large scan collections, and as a reference for using B2 as the durable, S3-compatible backbone of a high-write-amplification AI workload (each ingested page fans out to ~4 B2 objects).

What it looks like

Dashboard — archive metrics (documents, pages processed, pending, average recognition confidence, storage used), a 7-day OCR-throughput chart, and the most recent OCR runs.

Dashboard with OCR-archive metrics, throughput chart, and recent runs

Archive — the scoped explorer listing every scanned document with its collection, status, and recognition confidence, plus per-document Run OCR / view / edit / delete and a keyword search box.

Archive explorer listing scanned documents with status and confidence

Document detail — the scan beside its PaddleOCR detection overlay, the recognized full text, and per-region confidence scores.

Document detail showing the scan, detection overlay, recognized text, and per-region confidence

Keyword search — searching recognized text opens a results panel with matching pages and highlighted snippets, served from the rebuildable B2-backed index.

Archive keyword search returning matching pages with text snippets

Ingest — a dropzone plus per-scan OCR configuration (language, page-orientation detection, and a collection label) for adding new pages to the archive.

Ingest page with OCR configuration form and a drag-and-drop upload zone

The 4-step workflow

  1. Ingest a scan (TIFF / JPEG / PNG) → stored at raw-scans/<doc-id> on B2 with a config sidecar; the document starts as pending.
  2. Run OCR locally → PaddleOCR recognizes the page and writes ocr-results/<doc-id>/{result.json, overlay.png, text.txt} to B2; status flips to processed.
  3. Search recognized text → the SQLite keyword index returns matching pages with snippets.
  4. Review / edit / delete → inspect the scan next to its detection overlay, adjust OCR config for the next run, or remove the document (scan + all artifacts).

What you get

  • Local OCR (PaddleOCR) — text detection, angle classification, and recognition run entirely on-device. No second API key, no per-page cost, no data egress.
  • Scoped Archive explorer (/archive) — the app's primary surface: list documents with status, confidence, collection, and a thumbnail; run OCR, view, edit, or delete each; keyword search box on top.
  • Full-bucket File explorer (/files) — the reusable B2 browse / preview / download / delete surface, kept from the starter kit.
  • OCR overlay — detected bounding boxes drawn over the scan and stored on B2 for visual detection QA.
  • Keyword full-text search — a rebuildable SQLite index over recognized text; a "Reindex" action repopulates it from B2.
  • Archive dashboard — documents ingested, pages processed, pending vs processed, average recognition confidence, storage used, and an OCR-throughput chart.

Quick Start

You need: Node.js >= 20, pnpm >= 9, Python >= 3.11, Docker (the OCR service runs in a container — on macOS start it with Colima: colima start), and a free Backblaze B2 account.

1. Install frontend dependencies

pnpm install

2. Set up the backend venv (for tests + lint)

cd services/api
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt           # core API — enough for `pnpm test:api` / lint (OCR engine mocked)
cd ../..

The heavy OCR deps (PaddleOCR + PaddlePaddle) are not installed on the host — they run in the Docker container (see Running the OCR service below). The host venv only needs requirements.txt for the mocked test suite and linting.

3. Add your B2 credentials

cp .env.example .env

In the Backblaze B2 dashboard:

  1. Create a bucket → paste its Bucket Unique Name into B2_BUCKET_NAME. Set B2_REGION to the bucket's region slug (e.g. us-west-004); the S3 endpoint is derived as https://s3.<B2_REGION>.backblazeb2.com.
  2. Create an application key with Read and Write → paste keyID into B2_APPLICATION_KEY_ID and applicationKey into B2_APPLICATION_KEY (shown once).

4. Run it

colima start   # start Docker (macOS) if it isn't already running
pnpm dev

Frontend at localhost:3000, API at localhost:8000. pnpm dev runs pnpm doctor first — a preflight that catches a missing venv, placeholder .env, wrong tool versions, and busy ports.

Running the OCR service (Docker)

pnpm dev builds and runs the FastAPI OCR service in a linux/arm64 container (the web app stays on the host and talks to it over HTTP via NEXT_PUBLIC_API_URL). Docker is a prerequisite — on macOS start it with colima start.

Why containerized: the macOS-arm64 paddlepaddle CPU wheel hangs at 100% CPU on the first kernel dispatch on Apple Silicon. Running the exact same code in a linux/arm64 container (via Colima) dodges that broken wheel and executes paddle natively-fast on the same Apple Silicon hardware.

  • First build takes ~5–10 min — it installs paddle + deps and bakes the OCR models into the image so the first request doesn't pay the download cost. Later starts are fast.
  • The SQLite index + counters under /app/data persist in a named Docker volume (ocr-data).
  • Tear the container down with pnpm dev:api:down.
  • Tests and lint still run on the host venv (pnpm test:api, pnpm lint:api) with the OCR engine mocked — no Docker needed for those.

Commands

Command What it does
pnpm dev Start frontend (host) + OCR API (Docker container)
pnpm dev:web Frontend only
pnpm dev:api OCR API only — builds + runs the linux/arm64 container
pnpm dev:api:down Stop + remove the OCR API container
pnpm build Type-check + build frontend
pnpm lint Lint frontend
pnpm lint:api Lint backend (ruff)
pnpm test:api Backend tests (OCR engine is mocked — no ML install needed)
pnpm check:structure Verify layering rules
pnpm test:e2e Playwright e2e tests (run pnpm --filter @paddleocr-document-archive/web exec playwright install chromium once first)

Tech Stack

  • TypeScript, Next.js 16, React 19, Tailwind v4, shadcn/ui, Recharts, TanStack Query
  • Python 3.11+, FastAPI, boto3, Pydantic v2, Pillow
  • PaddleOCR + PaddlePaddle (local OCR, isolated in services/api/requirements-ml.txt)
  • SQLite (stdlib) for the rebuildable keyword index
  • Backblaze B2 (S3-compatible object storage) — single source of truth
  • pnpm workspaces (monorepo)

Core Features

Documentation Map

Doc Purpose
AGENTS.md Agent table of contents — start here
ARCHITECTURE.md System layout, layering, data flows
docs/features/ Feature docs
docs/app-workflows.md User journeys
docs/dev-workflows.md Engineering workflows and testing
docs/SECURITY.md Security principles
docs/RELIABILITY.md Reliability expectations
docs/exec-plans/ Execution plans and tech debt tracker

License

MIT License — see LICENSE for details.

Claude Agent B2 Skill

Manage Backblaze B2 from your terminal using natural language (list/search, audits, stale or large file detection, security checks, safe cleanup).

Repo: https://github.com/backblaze-b2-samples/claude-skill-b2-cloud-storage

About

Self-hosted OCR document archive: PaddleOCR turns scanned pages into searchable, structured text locally — no external OCR API — with Backblaze B2 (S3-compatible) as the single source of truth and a rebuildable SQLite index for keyword search.

Topics

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages