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

# ES modules

> How Cairn decides between classic scripts and ES modules, and what changes when a script is a module.

Every JS script has a **Delivery type**, set in the **Scope & loading** sheet:

* **Auto** (default): delivered as a module when the code uses `import` / `export`, otherwise as a classic script.
* **Classic script**: always delivered as a plain `<script>`.
* **ES module**: always delivered as `<script type="module">`.

CSS is never affected. This setting only exists for JS.

<Note>
  There's also a site-level "load all scripts as modules" override. When it's on,
  Auto scripts are delivered as modules even without `import`/`export` syntax.
</Note>

## What changes when a script is a module

The editor shows a **Delivered as ES module** status bar whenever a script will ship as a module, because modules behave differently from classic scripts:

* **Isolated scope**: top-level `const` / `let` / `function` declarations stay private to the module, they aren't global. If another script needs them, assign to `window` yourself: `window.mySlider = mySlider`.
* **Deferred**: modules run after the HTML is fully parsed, no matter what load order or execution timing you set.
* **`import` works**: you can import packages straight from a CDN:

  ```js theme={null}
  import gsap from 'https://esm.sh/gsap@3.12.5';
  ```

  Cross-origin imports need the CDN to send CORS headers. The major JS CDNs (jsDelivr, esm.sh, unpkg) all do.

## Runtime import warnings

When a module imports from a URL, the editor lists every origin the script will load code from at runtime, and flags two situations:

* **Untrusted**: the host isn't on Cairn's [trusted CDN list](/essentials/dependencies#the-cdn-allowlist). The import still works, but you're trusting that origin to run code on your site.
* **Unpinned**: the URL has no version (or uses `@latest`), so the CDN can serve different code tomorrow than it does today. Pin a version (`gsap@3.12.5`) so your site doesn't change behavior without a publish.
