Skip to content

case_study

Textquill

On-device OCR + offline grammar checker (Chrome extension)

Solo — product design, engineering, and release

  • JavaScript
  • Chrome MV3
  • WebAssembly
  • onnxruntime-web
  • Chrome built-in AI
Textquill: On-device OCR + offline grammar checker (Chrome extension)

problem

The problem

Getting text out of an image is a daily chore — a screenshot, a slide, a scanned invoice, a photo of a page — and almost every OCR tool solves it by uploading your image to a server. For anything sensitive (IDs, invoices, private documents) that is a non-starter, and even when it isn't, it's slow and gated behind accounts and quotas.

V1 solved the capture half. But extracted text is rarely finished text: OCR output is messy, it's often in a language you don't read, and it needs fixing before it's usable. Every tool for that second half — grammar checkers especially — has the same flaw as the OCR tools, only worse: they read everything you type, on every site, on someone else's servers.

So V2 set a harder constraint. Do the whole loop — recognize, proofread, translate, rewrite — with nothing leaving the machine, inside a Manifest V3 extension whose CSP forbids unsafe-eval and whose service worker can't run WASM directly.

approach

What I engineered

  • Ran the entire pipeline on-device in WebAssembly: OCR (Tesseract + PaddleOCR), a Rust→WASM grammar engine, a local translation model, and Chrome's built-in on-device model for AI writing tools. No account, no API key, and no network round-trip for user content — only two one-time static model downloads.
  • Built an always-on grammar checker that works everywhere you type: coloured inline underlines in any site's editable fields, click-a-word suggestion cards, US/UK/AU/CA dialects, and global plus per-site off switches. Password and search fields are never read, and because the checker is local it works in browsers with no cloud AI at all, including Brave.
  • Added a second OCR engine — PaddleOCR PP-OCRv4 on onnxruntime-web — hand-rolled rather than wrapped: DB detection post-processing and CTC greedy decode written in plain JS to avoid an OpenCV build whose Emscripten dispatch needs unsafe-eval, which MV3's extension CSP forbids. Low-confidence results cross-try the other engine and keep the better read.
  • Grew OCR to 38 languages with script-based auto-detect, and kept every V1 capture path (right-click, area-select, visible and full-page scroll-stitch, upload, drag-drop, paste, image URL, data URL) while adding PDF input with page ranges and password support.
  • Made the output actually reusable: regex find-and-replace with capture groups, text-to-speech, and export to .txt, .md, .csv, .html, .json, .xml, print, and .docx — the last through a dependency-free OOXML writer rather than a multi-megabyte library.
  • Kept the package honest under the store's size and review bar: dropped 24MB of never-loaded Tesseract cores and 160KB gzipped of pdf.js asm.js fallbacks, and gated the Chrome-AI actions behind a real diagnostic (with model-download progress and ETA) instead of hiding them or letting them fail silently.

result

The result

A shipped V2 that changed what the product is: not an OCR utility, but a private text pipeline — capture, read, correct, translate, rewrite — where the image and the writing both stay on the user's machine.

It's live and free on the Chrome Web Store, with its own site at textquill.app and a privacy policy that documents the exact network behaviour. Install it below.

38
OCR languages
4 local models
OCR · grammar · translation · AI
100% on-device
images and writing never leave the browser

Product facts for Textquill V2, my own free Chrome extension (2026). No usage or adoption figures are claimed.Install on the Chrome Web Store

more_free_tools

More free tools I've built

Prompt Vault

Free AI prompt manager (Chrome extension)

work_with_me

Have a project like this?

Tell me the problem on a 20-minute call and I'll tell you how I'd approach it, the same way Textquill started.

Discuss your project