← Back to journal

ESSAY

I Built a Scanner in a Day. Scanning Was the Easy Part.

For thirty years, buying off the shelf beat building, because building was expensive. That trade just changed, and the thing you get back is software that knows which deal it is looking at.

On a Saturday, between about half past ten in the morning and a quarter to eight at night, I built a document scanner for my phone. Capture, cropping, on-device text recognition, a searchable library, import from Photos and Files. It works. I have used it on real closing paperwork.

I am not telling you that because building a scanner is impressive. It is not. There are twenty of them in the App Store and several are very good. I paid for one of them for a long time.

I am telling you because of why I stopped using the one I paid for, and because I think the reason generalizes to almost every piece of software you currently rent.

The paid app ends at the PDF

That is not a criticism. It is the product. You point it at paper, you get a clean file, and the transaction is complete. Every scanner on the market is built to that finish line because it is the only finish line that is the same for all of their customers.

Here is what I actually needed. I sign a purchase contract. Somewhere in that document are a price, a closing date, an earnest money amount, and the names of the parties. I already have a system that tracks the deal that contract belongs to. What I want is for those two facts to touch each other, without me retyping anything, so that the contract shows up on the deal's timeline next to the calls and the offers, and so that when I go to underwrite, the number is already there.

No scanner can do that, and it is not because they are lazy. It is because that last connection is specific to me. It requires knowing what a deal is in my business, what a property record looks like in my system, and which four numbers out of a fourteen-page contract I actually care about. There is no version of that a vendor can put in a box and sell to a hundred thousand people.

So the scanning was the commodity. The last inch was the whole point, and the last inch is the part that was never for sale.

What the last inch looks like

The scan does not end at a file. It ends as an event.

When a document is captured, the system pulls out a fixed set of fields, writes them as structured data against the deal, and emits a record to the same ledger every other part of my operation writes to. Marketing writes there when a flyer goes out. Rehab writes there when a scope changes. Disposition writes there when a deal moves or dies. Now paper writes there too, in the same shape, so a settlement statement appears in the timeline in the same list as a phone call from three weeks ago.

The document library on a test device. Every document shown is synthetic.

Look at what is in that list, because the range is the argument. A title commitment. A purchase contract. A settlement statement. A deed. And a water service activation, which is the least glamorous piece of paper in this business and the one that tells you a person built this rather than a product team. Nobody designing a scanner for a hundred thousand customers puts utility paperwork in the demo. It only matters if you are the one who has to get the water turned on at a house you just bought.

That is the difference between an app and a system, and it is almost entirely unglamorous plumbing.

Two details from the build are worth pulling out, because they are the ones I would get wrong if I did it again.

Typed fields, not a summary. The obvious move is to have the model read the document and write a paragraph describing it. That paragraph is useless. You cannot compute with prose, you cannot compare it across ten deals, and a skill downstream cannot do anything with it except paste it somewhere. So the extraction returns a fixed set of named fields, and those names are treated as a contract that does not change. A summary is something a human reads once. A named field is something the rest of the system can build on for years.

On device by default. These are signed contracts. They have prices in them, they have people's names in them, and occasionally they have a Social Security number in them. So the default processing is the model that runs on the phone itself, offline, where the text never leaves the device at all. You can switch it to a cloud model in settings if you want more capability on a particular document, and it is deliberately a choice you have to go make rather than the thing that happens quietly.

That switch is worth noticing for another reason. Three different providers sit behind the same interface, interchangeable. I did not build that to be clever. I built it because I have already been through one cycle of watching capability move between vendors, and I would rather the thing I own be the part that does not have to move.

The part I could not have bought

There is one document in my business that broke everything.

A settlement statement is laid out in two columns, the buyer's side and the seller's side. Text recognition reads a page in lines, and on a two-column form those lines come out interleaved. You get a label from the left column, then a number from the right, then a label from the right, then a number from the left, in an order that looks plausible and is wrong. Which figure belongs to which line is genuinely not recoverable from the text, because the information is not in the text. It is in the layout.

No amount of better prompting fixes that. I tried, briefly, which is how I know.

What fixes it is that every recognized line comes with its position on the page. So instead of reading the document as a sequence of words, you read it as a grid: find the label, then take the number that sits on the same row, on that label's own side of the page. Ten fields, all correct, three of which check out against each other arithmetically.

Here is the part that matters for this essay. That only works because I know that a handful of specific line numbers appear in the same place on every settlement statement I have ever closed on. That is not engineering knowledge. It is the residue of having sat at a lot of closing tables. The build turned it into geometry.

That is the shape of the whole opportunity, I think. The generic capability is free now. What is left is whatever you know that the vendor does not, and the only way that knowledge becomes software is if you are the one holding the pen.

What real paper broke

The synthetic tests all passed. Then I ran actual documents through it and it found things I never would have caught.

The address detection confidently returned my own letterhead as the property address, on two different live scans. Pages I had deleted were still being handed to the model, which then produced a summary citing a termination clause that does not exist anywhere in the document. And one of the cleanup routines quietly trimmed a six-figure number down to four figures, which is exactly the kind of error that is invisible until it is expensive.

Every one of those was mine, not the model's. And every one of them is now a check that runs automatically, which is the only reason I am comfortable telling you about them.

Where it actually stands

The honest status: it scans, it extracts, and the connection into the deal system is built and tested. It has not yet run end to end against the live database. The document table is still empty and the tools that expose all of this to the rest of my stack are written but not deployed.

So the right word is wired up, not in production. I would rather say that now than let you assume otherwise and quietly fix it later.

The trade that changed

For about thirty years the calculation was simple. Building your own software cost more than it was worth, so you bought something close enough and lived with the gap. The gap was real and everyone accepted it. Your tools did not know about each other, none of them knew anything specific about how you work, and the integration work to fix that cost more than the tools did.

That calculation has quietly inverted for a whole class of things. Not for your accounting system and not for anything with real regulatory weight. But for the layer that sits between the software you rent and the way you actually run, the cost of building has fallen far enough that the question is no longer whether you can afford to build it. It is whether you can afford for it not to fit.

Off-the-shelf software is designed for the average of a hundred thousand customers. That is a feature when the problem is generic and a tax when it is not. The tax used to be unavoidable. It is not anymore, and the people who notice that first are going to end up with operations that fit them the way a good tool fits a hand.

I did not build a scanner because I needed to scan things. I built it because the paperwork was the last part of my business that did not know what deal it was looking at.