Receipt Scanner
A private expense archive with receipt upload, async extraction, user correction, review and confirmation, archive search, monthly summaries, CSV export, and smoke proof.
What it is
Receipt Scanner is a corrected, searchable archive of personal spending proof. OCR is infrastructure, not the product itself.
The useful user loop is upload, extract, review, correct, categorize, search, summarize, and export.
The loop it has to make believable
- 01
Built the async ingestion shape: immediate upload acknowledgement, private object storage, background OCR/parsing, status transitions, and review-needed records.
- 02
Added JWT auth, per-user ownership, account deletion, Flyway migrations, file validation, MinIO/S3-compatible storage, presigned previews, and category/monthly analytics.
How it’s built
The backend shape is a modular Spring Boot app with auth, storage, validation, background processing, OCR abstraction, parsing, statuses, and analytics.
The current proof path is local: backend tests, Testcontainers integration setup, frontend build, and `scripts/smoke.sh`. It should still not be presented as a hosted production product or a trained custom OCR system.
Architecture
- Product loop
- Register, upload image, process asynchronously, review/correct, confirm, search/filter, summarize, export CSV, delete account
- Pipeline
- Upload validates/stores private object, saves PENDING receipt, triggers worker, reads bytes for OCR, parses, and persists status/data
- Backend
- Spring Boot, PostgreSQL, Flyway, Spring Security JWT, S3-compatible storage, Google Vision optional, mock OCR default, Tika validation
- Boundary
- Experimental LayoutLM/FastAPI code under ml_service is not wired into the active runtime and should not be claimed as production ML
What has to hold up
- Kept OCR replaceable with deterministic mock OCR by default and optional Google Cloud Vision for credentialed runs.
- Added a repeatable smoke script that proves account creation, upload, processing, correction, review, confirmation, search, summary, CSV export, account deletion, and stale-token rejection.
How I would present it
I would present this as a local MVP with a real end-to-end backend loop, not as a polished deployed scanner.
That honesty helps: it shows judgment about what is built, what still needs production hardening, and why custom ML is deferred until user corrections create useful training data.
Proof
VerifyRepository, checks, stack, status
- 01
Open the GitHub repo.
- 02
Read the architecture and edge-case sections.
- 03
Follow the documented proof path: README, scripts/smoke.sh, JUnit/MockMvc/Testcontainers tests, frontend build script.
- Role
- Backend architecture, async OCR flow, auth, frontend shell
- Scope
- Private receipt and expense archive with reviewable OCR workflow
- Proof
- README, scripts/smoke.sh, JUnit/MockMvc/Testcontainers tests, frontend build script
- Stack
- Java, Spring Boot, PostgreSQL, Flyway, MinIO/S3, React, Vite
- Backend
- Spring Boot 3.4
- Java
- 21
- Storage
- MinIO/S3
- Proof
- smoke.sh