Skip to main content
Some environments run JavaScript but can’t serve files alongside it — a notebook cell, a sandboxed iframe, a browser extension, a playground that hands you code as a string. A large WASM runtime is usually fetched from a known URL at startup; when there is no URL to fetch from, the code has to come from bytes you already hold in memory, loaded through a blob URL (URL.createObjectURL(new Blob([bytes]))). The embed entry point is built for that. The worker and core modules are packed into a single import-free file, so you can load the whole runtime from a blob and pass the engine bytes in yourself.
That is the whole flow: load the entry from a blob, hand over the engine bytes, and create the sandbox. With a bundler, import { Sandbox } from "@capsule-run/vpod/embed" resolves to the same file and inlines it for you. The example above avoids the bare package name on purpose: it fetches the file and loads it from a blob, so it runs from a plain HTML page with no bundler and no import map to resolve the name.

What you supply

dist/embed/vpod.js is a single file with no imports, around 0.6 MB, with the worker and the small core modules already baked in. Load it however your host loads code, including from a blob. The one thing it cannot bake in is the engine itself, so you pass it:
Where those bytes come from is your problem to solve, which is the point: a host that already ships large wasm payloads has a way to do it, and vpod stops guessing at URLs.
Handing over the engine is the trade for a caller with nothing to serve from. It does mean the browser cannot cache it between visits or stream-compile it the way it does on the default path, so a page that can serve files is better off with the normal browser build.