Build1 distinct publisher3 min readPublished
Running document OCR inside the tab takes the third party out of the data flow, and with it the processor agreement. What replaces it is a first load of about 6 MB of OCR weights plus a 580 MB default entity model.
The Engineer · Build desk

Compiled by The EngineerSomething wrong?How this is made
The composition model is the part I would copy even if I never shipped inference to a browser. Each stage reads one named field on a per-page row and writes another: `PdfToImage` writes `image`, `PaddleTextRecognizer` reads it and writes `text`, `GlinerNer` reads that and writes `ner` [7]. That is the same contract the Python ScaleDP library uses on Spark [7], and it gives a debug session stage boundaries. Empty `ner` with populated `text` is a model problem. Empty `text` is a rendering problem.
The byte budget is where the design gets awkward. Six plus 580 is 586 MB on a cold profile [17], and the entity model is roughly 97 times the size of the recogniser [20]. Swapping the default for `gliner-pii-edge` cuts 399 MB, landing near 187 MB, and IndexedDB caching means a browser profile pays once rather than per document [18][15]. The first visit still pays [15]. Downloading 580 MB to skip a form looks like a poor trade until you have waited in the queue for the form [4].
At the quoted hosted rates of $0.50 to $1.50 per thousand pages plus egress [5], the compute spend you displace is not what carries the decision. The author's own example workload, 10,000 pages a night [6], is $5 to $15 a night, or $1,825 to $5,475 a year before egress [19]. That is a rounding error against the artefacts the hosted third box drags into procurement [3]. The interesting saving is administrative, and the post is straight about it: with no third party in the path there is no processor, so the agreement is not merely easier to obtain, it does not apply, and "how long do you keep it" is answered by the tab closing [10].
Treat the 200 ms re-run figure as a measurement of somebody's laptop [12]. For it to transfer, three things have to hold on your users' machines: the weights are already cached, the changed parameter invalidates only downstream stages, and if the change is upstream there is enough local CPU to re-render the PDF at 300 dpi [9]. The library does not assume any of that. `isWebGpuAvailable` and `isCrossOriginIsolated` report what the tab actually got, because WebGPU may be absent and threads depend on response headers the host may never send [16]. Reporting the environment rather than assuming it is the part of this package that reads like it has been run somewhere real.
In my context the trade is worth taking for low-volume sensitive work: a few files per session, a reviewer moving thresholds, data that would otherwise need a signed processor agreement [10]. It is the wrong trade for a nightly batch, and the post says so rather than pretending otherwise [6].
Ranked by verification strength, evidence, and original report placement.
A dev.to post written 2026-09-03 documents browser-native OCR with code examples targeting @stabrise/[email protected], assuming no prior OCR or ONNX knowledge.
@stabrise/scaledp runs PDF rendering, text detection, OCR and entity recognition on onnxruntime-web, inside the browser tab, with no upload of the document.
The post draws any hosted document API as three boxes (your app, their API, their storage plus GPUs) and says the third box is why OCR procurement involves a data processing agreement, a retention policy, a sub-processor list and a conversation with whoever owns compliance.
The author's line on hosted OCR adoption: "The engineering is five lines; the approval is five weeks."
The author states that for 10,000 pages a night hosted APIs are the correct answer.
The pipeline emits one row per page; each stage reads a named field on the row and writes another, with PdfToImage writing image, PaddleTextRecognizer reading it and writing text, and GlinerNer reading that and writing ner, which is the same composition model the Python ScaleDP library uses on Spark.
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · September 3, 2026
Follow any of these and your For You feed starts watching them — no settings page required.
build
Browser-side inference hands the GPU bill to the user's laptop1 distinct publisher
build
Spline V2 turns the 3D editor into an endpoint, with the desktop app as the only door1 distinct publisher
build
The repo's own control run deleted the 5-10x WASM claim from vizcrush's launch copy1 distinct publisher
build
A browser video editor pays for its missing upload button in runtimes, caches and determinism1 distinct publisher
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
One vendor's numbers, checkable in principle, unchecked here
The API surface is verifiable — the code in the dev.to post either runs against 0.1.1 or it does not, and the demo invites you to watch the network panel yourself. Everything else traces to the library's own author: 6 MB of OCR weights, 580 MB of entity model, $0.50–$1.50 per thousand hosted pages. The two claims that would actually change a purchase decision, the market price band and 'no processor agreement is needed', are the two with no independent support anywhere in this reporting.
A version number and a demo page
Adoption evidence stops at 0.1.1 on npm and a hosted builder you can drop a PDF into. No named user, no download figure, no production deployment, no one outside StabRise on record. That is what pre-1.0 looks like, and the post does not pretend otherwise — its call to action is to try the demo, not to point at who already shipped.
Technically candid, legally ahead of itself
Most vendor posts do not concede the case. This one does: a server wins at volume and it is not close, the 580 MB is real and unavoidable for good multilingual entity extraction, and 'open more tabs' is not a scaling story. The stretch is elsewhere. Turning 'nothing is uploaded' into 'the processor agreement is not needed' is a compliance ruling delivered in a code tutorial, and the readiness implied by a polished walkthrough runs ahead of a 0.1.1 package with no disclosed users.
The maker writing about the make
StabRise ships both the browser package and the Python sibling the post recommends when browsers stop making sense, the code is AGPL-3.0-or-later with commercial licensing available from the same company, and the piece closes on an install line and a demo link. The frank accounting of the 580 MB does not offset that interest — it is the most effective way to serve it.
Specific enough to falsify, thin enough to withhold judgement
We hold this loosely. The mechanics are precise and self-consistent, and the numbers are the kind anyone can disprove in an afternoon with a network panel — which raises confidence in the description of the library. It stays low on everything that matters commercially: no second account, no accuracy comparison against the hosted APIs being displaced, no legal read on the central procurement claim, and no user beyond the vendor.