# One page, one config, one script.

> Install ApiGlow with one script tag: the canonical snippet, openapi.url vs openapi.spec, static hosting, self-hosting from npm, and an agent prompt.
>
> Source: https://apiglow.dev/docs/install/index.md


## The whole install

{{< install-snippet >}}

That is the complete installation, not an excerpt. `app.js` self-initializes: it reads the config block, injects its own CSS from next to the bundle, and builds the UI in the page. There is nothing to build, generate or run on a server.

The `src` above points at a public CDN. To depend on nothing outside your own origin, [serve the bundle yourself from npm](#serving-it-yourself-from-npm). Only that line changes.

Two things about the config block:

- Its id is `api-doc-config`, and the fallback global is `window.API_DOC_CONFIG`. The `apidoc` prefix is intentional and stable, so that renaming the product never invalidates a deployed page or its readers' stored data. Copy it verbatim — do not change it to `apiglow`.
- It is strict JSON, since it lives in a `type="application/json"` script: no comments, no trailing commas. To keep comments in your config, use the `window.API_DOC_CONFIG` fallback in a regular script instead.

## `openapi.url` or `openapi.spec`

One key is required: where the schema is.

- `openapi.url` points at an OpenAPI 3.0.x, 3.1.x or 3.2.x document, JSON or YAML. A Swagger 2.0 document is converted at load. If the server hosting it is not the docs' origin, it must allow cross-origin reads — see [Try-it & CORS](/docs/cors/).
- `openapi.spec` carries the document itself, as a JS object or a JSON string. There is no request, so no CORS to negotiate. In exchange, the page carries the schema's weight and must be redeployed on every API change.

When both are set, `spec` wins. For several APIs in one installation, use `openapi.specs` — it has [its own guide](/docs/multi-spec/).

## A fuller config

Everything beyond `openapi` has a default. The block below shows the shape of the common options; the [configuration reference](/docs/configuration/) documents every key.

```json {title="api-doc-config"}
{
  "openapi": { "url": "https://example.com/openapi.json" },
  "theme": { "default": "light", "available": ["light", "dark", "corporate"] },
  "language": { "default": "en", "available": ["en", "fr"] },
  "environments": [],
  "docsPages": [],
  "scenarios": [],
  "features": { "scenarios": true, "audit": true },
  "tryIt": { "proxyUrl": null },
  "history": { "maxEntries": 500, "maxAgeDays": 30 }
}
```

## Hosting

Any static HTTP(S) hosting works — an S3 bucket, GitHub Pages, a folder behind nginx.

**`file://` does not work.** The app is an ES module and fetches its assets, and browsers block both from local files. For a quick local look, use a one-line static server such as `npx serve` or `python3 -m http.server`.

## Serving it yourself, from npm

The snippet above loads the bundle from a public CDN. To keep your documentation from depending on anything outside your own origin — an intranet, an air-gapped network, a CSP with no third party in it — install the package and serve its `dist/` yourself. One line of the snippet changes.

```bash {title="Once, in your build"}
npm install apiglow
cp -r node_modules/apiglow/dist static/apiglow
```

```html {title="index.html"}
<script src="/apiglow/app.js" type="module"></script>
```

The config block is unchanged. You gain the version pinned in your lockfile, reviewed and upgraded like any other dependency, and no request leaving your origin at runtime.

Whatever your build already does to publish static files will do: Vite's `publicDir`, a webpack copy plugin, a `cp -r` in CI. There is nothing to compile.

**Keep `app.js` next to the rest of `dist/`.** It resolves `app.css`, the `i18n/` language packs and `fonts/` relative to itself, and two scripts it loads only when needed: `audit.js` when someone opens the [schema audit](/docs/audit/), `read-document.js` for a schema with a syntax error in it. All of them must stay siblings wherever you publish them. Copy the directory, not the file.

That same resolution is why ApiGlow does not go through a JavaScript bundler. Inlined into one of your chunks, `app.js` looks for its stylesheet and its language packs next to your code, finds neither, and renders the documentation unstyled. Install it, serve it, and point a `<script>` at it.

## Let an agent do it

If an agent is doing the installing, hand it this prompt as-is:

{{< ai-prompt label="Have an agent install it for you" >}}

