> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vpod.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Embedding

> Load the whole runtime from a blob URL, with nothing to serve.

Host applications that already ship pyodide, ffmpeg or v86 load them from a blob
URL. The default build cannot work that way: it is a multi file ES module package
with chunked entry points and module workers, so its pieces have to be reachable
at real URLs. Integrators without anywhere to serve from ended up routing it
through a service worker just to make relative imports resolve.

The `embed` entry point exists for exactly that case.

```ts theme={null}
import { Sandbox } from "@capsule-run/vpod/embed";

const sandbox = await Sandbox.create({
    coreModules,                    // the engine, as one ArrayBuffer
    snapshot: { bytes, name },      // or a registry name
});
```

That is the whole surface. You hand over the bytes and vpod does the rest: no
worker to wire up, no blob URL to create or revoke, no URLs of any kind.

## 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:

|      |                                                            |
| :--- | :--------------------------------------------------------- |
| File | `dist/component/vpod.core.wasm` from the installed package |
| Size | around 25 MB                                               |
| Type | one `ArrayBuffer`                                          |

```ts theme={null}
const source = await fetch("/assets/vpod.core.wasm");
const coreModules = await source.arrayBuffer();
```

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.

<Note>
  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](/sdk/typescript/browser).
</Note>

## Pulling a snapshot by name

A registry name works, but the URL has to be absolute. Code loaded from a blob has
no base to resolve a relative one against:

```ts theme={null}
const sandbox = await Sandbox.create({
    coreModules,
    snapshot: "vsnap-base-256mb",
    registryUrl: "https://registry.vpod.sh/snapshots.json",
});
```

## Networking

Networking follows the same rule as the rest of the browser build: it needs the
page to be cross-origin isolated, so it needs the two headers described in
[Running in a browser](/sdk/typescript/browser). Without them the sandbox still
boots and still runs commands, it just has no network.
