The Browser APIs Behind the OnePassApps Studios: Four Jobs Traced
I work on OnePassApps. This post is a measurement of our own build in the live tab, and it covers a layer none of our other posts has touched: which browser platform APIs the Studios actually call, and what happens when
I work on OnePassApps. This post is a measurement of our own build in the live tab, and it covers a layer none of our other posts has touched: which browser platform APIs the Studios actually call, and what happens when one of them is not there.
The method is the whole point, so here it is first. I attached to the page before its own scripts ran and put counting proxies around 18 platform APIs: crypto.subtle.digest, FileReader, File.arrayBuffer, Blob.arrayBuffer, Blob.text, createImageBitmap, OffscreenCanvas, canvas.getContext, canvas.toBlob, Worker, CompressionStream, DecompressionStream, TextEncoder, TextDecoder, URL.createObjectURL and navigator.clipboard.writeText among them. I also probed 44 platform features for plain availability. Then I did real work in four studios and subtracted the calls the page had already made at load time, so every count below belongs to the job rather than to the page.
One honest note about the method. My first pass wrapped performance.now and fetch with plain functions, and the app stopped working in the tab. The app was fine; my wrapper was not. Code that extracts a method into a bare variable and then calls it unbound - React's scheduler does exactly this with performance.now - makes the native function throw. I rebuilt the wrappers as Proxies that preserve construction, and the same four jobs then ran clean. A trace that breaks the thing it traces is worth warning you about.
The four jobs, and what each one called.
Job one: the File Studio, File hash tab, a 34-byte file. During the job: one Worker, two TextDecoder.decode calls, one canvas.getContext. The result panel read "Calculated in 0.2 s", algorithm SHA-256, file size 34 B. The digest on screen matched Python's hashlib.sha256 for the same bytes, exactly.
Job two: the Image Studio, Resize tab, a 64 by 48 PNG, 3.6 KiB. During the job: six Blob.arrayBuffer calls, one createImageBitmap, one canvas.getContext, one URL.createObjectURL, two TextDecoder.decode. The panel read "Image ready. Processing stays in this browser." with the fit shown as 100% and 100%.
Job three: the Data Studio, To JSON tab, a three-row CSV. During the job: one Blob.text, one Worker, two TextEncoder.encode, two TextDecoder.decode, one canvas.getContext. The panel read "Converted 3 rows to JSON", Format JSON, Size 185 B, Lines 17, "Converted in 278 ms".
Job four: the Text Studio, Base64 tab, typed text. During the job: two Worker constructions, two TextDecoder.decode. The panel read "44 characters - 1 line" and "Encoded in 0.1 s".
Then the experiment that tells you where the work happens.
The hash does not run on the main thread. I replaced the main thread's crypto.subtle.digest with a stub that throws, reloaded the Studio, and hashed the same 34-byte file again. The Studio still reported "Calculated in 0.2 s" and still produced the same digest, 471726b46843b08aaeeb24756fb5dcd5a74587791300f75888fac7898a0e382d. A digest computed in a Worker cannot be affected by what the main thread does to crypto.subtle, so the SHA-256 is computed off the main thread. The CSV conversion behaves the same way, with a Worker per conversion. That is the reason a large file does not freeze the tab you are looking at.
What the app asks of your browser, in total.
Of the 44 features I probed for availability in the browser I tested, 41 were present and three were not: navigator.share, WebGL2, and navigator.scheduler.postTask. None of the three appears in any of the four job traces, so nothing in these paths depends on them. WebGL2 being unavailable in this browser is worth noting on its own, because it means the browser had no GPU canvas path available and the Studio did not care.
Four heavier primitives were present and were not called in any of these four jobs: OffscreenCanvas, WebAssembly, CompressionStream and DecompressionStream. Read that narrowly. It is a statement about a hash, a resize, a CSV conversion and a Base64 encode, not about every tab in the app - I did not run every tool in this round, and the Image Studio's remove-background tab runs an on-device model that I left alone. Equally, the File System Access API, showOpenFilePicker and showSaveFilePicker, was available and unused: the Studio takes its files through an ordinary file input.
For context, the JavaScript behind all of this is four files totalling 870,507 bytes: app-shell-shared at 369,077, the main index chunk at 321,812, a React vendor chunk at 178,924, and a 694-byte runtime.
What I did not measure, plainly.
One browser: Chromium 156 on Linux, one build of the app, 4 November 2026, signed out. I did not run Firefox, Safari or Edge, so this post cannot tell you what they do. What it can tell you is which APIs we call, so you can look them up yourself in your own browser's console.
The proxies count calls, they do not explain them. Six Blob.arrayBuffer calls during a resize is a count, not a reading of what each call did.
I did not measure memory use, I did not measure how long a large file takes, and I did not test the tools that need a real media file, a model download or a network request.
If you want the tour rather than the trace, the guides are here: https://app.onepassapps.com/guides?utm_source=devto&utm_medium=post&utm_campaign=browser-api-trace&utm_content=guides-link
Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.