# Converting a project to UNPKG file lookups

## Principles

- Prefer the original UNPKG file lookup: `https://unpkg.com/<package>@<version-spec>/<file>`.
  Do not route through esm.unpkg.com unless the package has no browser-ready
  file and the user accepts the beta service.
- Preserve the project's version intent. Keep exact pins exact and ranges as
  ranges unless the user asks to change policy. For new dependencies, a
  patch-level specifier (e.g. `preact@10.26`) is a good production default:
  bug fixes flow automatically while major/minor changes stay deliberate.
- Only runtime browser dependencies are candidates. Never convert
  devDependencies, build tools, test tooling, SSR/framework internals, or
  packages whose entry points use Node.js builtins.
- Trust the audit classifications. `convert_carefully` and `needs_review`
  mean exactly that — verify in a browser or keep the dependency bundled.

## Framework apps: standalone surfaces only

If the project uses a framework (next, nuxt, @sveltejs/kit, @remix-run/*,
astro, gatsby among its dependencies), the framework owns its runtime
packages. React in Next, Vue in Nuxt, and friends must stay bundled: the
framework renders with its own copies, and a CDN copy duplicates the
runtime and fights SSR/hydration. Pass the framework option to
audit_dependencies (it also auto-detects) so those packages are
classified in context.

For a framework app, UNPKG conversion applies only to standalone browser
surfaces outside the framework's rendering: a no-build static page, an
embedded widget, a docs snippet, a marketing island served as plain HTML.
"Keep everything bundled" is the correct recommendation for the framework
app itself; say so plainly instead of forcing conversions.

Build-time things are never candidates even when they sit in
dependencies: CLI tools (anything with a bin field), types-only
packages (@types/*), PostCSS/Tailwind plugins, and framework tooling.

## Audit workflow

1. Read the project's package.json (runtime dependencies only), existing
   import maps, HTML entry files, and bundler config.
2. Call `audit_dependencies` with the dependency name/spec map.
3. Present the plan grouped by classification before editing, unless the
   user asked you to apply changes directly.
4. For `convert_now` entries, add import-map entries (or script tags for
   classic scripts) using the suggested URLs. If an entry lists bare
   imports in its reasons, its suggested URL already uses ?module to
   rewrite them (or names the peers to map); a plain file URL whose entry
   imports unmapped bare specifiers will not execute standalone.
5. Remove converted packages from the bundle only when the bundler setup
   makes that clean (externalize or remove the import); otherwise leave the
   dependency installed and note it.
6. Verify: call `verify_url` for each new URL and validate the map with
   check_importmap, then prove execution in a real browser where
   possible: the repo's scripts/verify-browser.ts loads the map in
   headless Chrome and reports which specifiers actually import. A URL
   returning 200 is resolution, not execution. Then run the project's
   own tests or open the page. A converted app that was not run is not
   done.

## URL rules

- Canonical form: `https://unpkg.com/<name>@<spec>/<file>` — scoped names
  keep their `@scope/` prefix.
- Use `build_file_url` rather than hand-assembling URLs when a file path
  or version policy matters; use `list_files` before guessing file paths.
- `?module` on a .js file rewrites its bare imports to UNPKG URLs. It is
  part of the direct file lookup, not a separate service.
- `?meta` on any package or directory URL returns JSON file metadata.

## What not to do

- Do not guess versions or file paths from memory; resolve them live.
- Do not convert every dependency. A mixed result (some CDN, some bundled)
  is the normal, healthy outcome.
- Do not add tracking parameters to UNPKG URLs.
