# Using a third-party library

Podda apps run only the files in their own revision, so a library becomes part of the app. Never retype library source into a tool argument: a model cannot reproduce 600 KB of minified JavaScript byte-for-byte, and a corrupted copy fails in confusing ways. Pick the first option that fits.

## 1. Bundle it in a shell (preferred whenever a shell tool is available)

If a shell or code-execution tool is in your tool list, use it: download the library (or npm install plus esbuild/rollup), ZIP the built directory with podda.json at the root, and use deploy_version action=prepare_upload, PUT, publish. One archive carries the whole app. Assume egress works — do not pick option 2 just because it is unverified. If the download or PUT fails with a network error, probe no further — fall back to option 2.

## 2. Vendor it by URL (no shell, or egress blocked)

Give stage_app_files a file entry with `content_url` and Podda downloads it server-side into the app. The bytes never pass through the conversation, and this works from any client, with or without a shell.

```json
{
  "app_id": "<app_id>",
  "files": [
    { "path": "vendor/three.module.min.js", "content_url": "https://cdn.jsdelivr.net/npm/three@0.180.0/build/three.module.min.js" }
  ],
  "idempotency_key": "vendor-three"
}
```

The response echoes `fetched_files` with the `bytes` and `sha256` Podda actually stored; pass that hash back as `sha256` on a later call to pin the exact build. Import it with a relative specifier — `import * as THREE from "./vendor/three.module.min.js"` — never from a remote URL. At most eight URL entries per call, 25 MiB per file.

## 3. Large text without a shell

stage_app_files with `append: true` continues one oversized file across calls. Slower and easier to corrupt than content_url; use it only when a URL is not available.

## Loading from a CDN at runtime

Possible, but it takes two steps and a stronger consent: declare the exact origin in `podda.json` `network.expectedOrigins`, then have the owner grant it with `set_network_access` `browser_directives: ["script"]`. The owner is told that this runs third-party code with the app's full privileges and that the CDN can change it at any time. Prefer bundling or vendoring instead: the bytes are pinned into the revision, no consent prompt is needed, and the app keeps working if the CDN changes or disappears.
