Serve the isolation headers first
SharedArrayBuffer and nothing loads. Every other problem is
downstream of this one.
Register a backend before initializing
autoRegister picks the CPU or WebGPU build for the current browser, so you do not have to
detect it yourself.
Read capabilities rather than assuming
images and segmentation have
no registered engine today. Check unavailable before putting a feature in the interface.
Respect the gesture rules
Three things need a user gesture, and all three fail silently or confusingly without one:RunAnywhere.storage.chooseDirectory()- microphone access
- audio playback
useEffect, not behind a timer.
Pick small models
A browser download is the user’s bandwidth and the user’s disk. A 4GB model is not a reasonable thing to fetch on a page load. Show the size before downloading, and default to the smallest model that does the job.Stream, and batch the DOM writes
Inference runs in a worker, so the main thread stays free. What stalls a page is writing to the DOM on every token. Batch withrequestAnimationFrame.
Cap output length
maxOutputTokens is the biggest lever on latency.
Unload what you are not using
insufficientMemory.
Close sessions on pagehide
Offer a real directory for repeat visitors
OPFS is the default and is wiped when the user clears site data. For anyone who will return,chooseDirectory() puts the models somewhere durable and turns a repeat 2GB download into
nothing.
One RAG session at a time
The web index is process-wide. Opening a second session while one is open throws. Close the first.Remember which methods are synchronous
models.list, models.get, models.register, llm.tools.*, and tts.stop are synchronous
on Web and async on the other SDKs. Code ported from Swift or React Native will have await
in the wrong places.