Turn a shoebox of family letters into one searchable PDF: transcriptions in front, photographs of the originals behind, and a clickable citation between every pair.
It is a small local web app. You run it on your own computer, it opens in your browser, and nothing is uploaded anywhere unless you deliberately switch on handwriting recognition.
The finished volume has two halves and they point at each other.
Printed page numbers match the numbers your PDF reader shows, so a citation can be typed straight into the page box. Bookmarks list every letter and every plate.
- Intake — drag photographs or scans in. Originals are copied and never altered.
- Cleanup — finds the sheet against the background, corrects perspective, deskews, lifts faded ink. Tuned for both phone photos and flatbed scans.
- Recognition — Tesseract for typed and typewritten pages, offline and free. Optional Anthropic API for handwriting, which Tesseract cannot read. Anything the machine was unsure of lands in a review queue rather than being trusted.
- Dates and provenance — type dates however you like (
12 March 1944,March 1944,1944,3/12/44); what you type sets how exact the date is, so a bare year is never printed as a day. Records where the date came from — the letter, the postmark, the envelope, or your reasoning — and prints that under the heading, so a reader can tell a copied fact from a deduction. The postmark is stored as it reads, and datelines found in the text are offered for confirmation, never applied silently. - Envelopes and enclosures — mark an image as the envelope and it is labelled as such on its plate, with the address set apart from the letter text instead of running into it.
- Binding — assembles the volume, laying it out repeatedly until every page number in every citation is correct.
- Export — plain .txt, .csv and .json, so the archive outlives this app.
Work you do by hand is protected: once you have typed or checked a transcription, no batch job will overwrite it — replacing it takes an explicit "discards my text" button.
If your dates live on postmarks rather than in the letters, the Catalogue is where you work: one editable row per letter, Enter jumps down a column like a spreadsheet, and Fill down copies a value into every row beneath it — three clicks to say a whole batch is Walter to Ruth, from Camp Shelby, dated from the postmark.
Already keep a list somewhere else? Download the catalogue as a CSV, fill in the columns, and import it back — rows are matched to letters by image filename, only the cells you fill in are changed, and anything that matches nothing is reported rather than silently dropped.
- Install Python — tick Add python.exe to PATH on the first screen of the installer.
- Install Tesseract, accepting the default folder.
- Download this repository (green Code button → Download ZIP) and unzip it.
- Double-click
setup-windows.bat. - Double-click
Start-Letter-Archivist.bat.
Your browser opens at http://127.0.0.1:5000. Leave the black window open
while you work.
INSTRUCTIONS.txt is the full manual — written for someone who has never used a command line, and worth reading before you photograph two hundred letters. It covers photographing technique, dating undated letters, transcription conventions, backups, and what to do when something goes wrong.
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
brew install tesseract # or: sudo apt install tesseract-ocr
python app.pypython tools/make_sample_letters.py sample_letterswrites five synthetic images — typed sheets, a wobbly hand, an addressed envelope with a postmark, and one shot at an angle on a dark table — so you can run the whole pipeline before touching anything irreplaceable.
Everything runs on your computer: the cleanup, Tesseract, the PDF. The single exception is handwriting recognition, which is off until you paste an Anthropic API key into Settings. When it is on, images of pages Tesseract could not read are sent to Anthropic's API for transcription. Leave the key blank to keep the app entirely offline and type handwritten letters yourself.
app.py the web pages and what the buttons do
archivist/config.py settings and folder locations
archivist/db.py the SQLite catalogue
archivist/images.py page detection, perspective, deskew, contrast
archivist/ocr.py Tesseract and Claude, and the routing between them
archivist/dates.py parsing typed dates, datelines, provenance
archivist/pdfbuild.py the finished volume, citations and all
templates/ the pages you see
tools/ sample letters and the test suite
Your archive — originals, cleaned copies, catalogue, and built PDFs — lives in one folder outside the code, so you can put it in Dropbox or on a USB drive and back up the whole thing as a unit.
python tools/test_end_to_end.pyBuilds a complete throwaway archive from generated sample letters and asserts
around a hundred and ten things about it — that page detection cropped the tilted photo,
that the recognised words carry positions, that a bare year is never printed as
a day, that an unreadable typed date leaves the existing one alone, that
undated letters sort last, that every citation in the PDF links to the page
it names, that re-running recognition leaves hand-typed transcriptions alone,
that an interrupted import can be resumed, and that the app's own pages all
load. Should print 0 failed.
A people index at the back. Place names on a map. EPUB output. A facing-page reading view with image and text side by side. Support for a second language. Pull requests welcome — this is meant to be handed around and improved.
MIT. Use it, change it, pass it on.



