Skip to main content

Every key, one page.

The config lives in the host page, in a <script id="api-doc-config" type="application/json"> block — or in the window.API_DOC_CONFIG global when you want comments around it. Only openapi.url (or spec, or specs) is required; every other key has a sensible default. Keys are grouped below as the config groups them; defaults are stated where one exists, as of v0.1.0.

The full config at a glance — copyable, one comment per key
config.js
// The same object, minus the comments, can live inline in the page as
// strict JSON: <script id="api-doc-config" type="application/json">{ … }</script>
window.API_DOC_CONFIG = {
  openapi: {
    // The only required key: your schema, JSON or YAML, CORS-readable.
    url: "https://example.com/openapi.json",
    // …or carry the schema in the page — no request, no CORS; wins over url.
    // spec: { openapi: "3.1.0", … },
    // …or several APIs in one install; almost every key below can be
    // redeclared per entry. Wins over url.
    // specs: [{ id: "payments", title: "Payments API", url: "…" }],
    // default: "payments",              // spec shown on arrival (multi-spec)
    // Documentation hiding, not access control — by tag, method + path,
    // path, or operationId.
    hide: ["tag:Internal", "DELETE /admin/*"],
    // OpenAPI Overlay 1.1 documents applied to the schema at load, in order.
    overlays: ["/overlays/fix-descriptions.json"],
    // A starting patch seeded into the reader's own overlay editor.
    userOverlay: null
  },
  theme: {
    default: "light",                    // first-load theme (default "system" follows the OS); the reader's choice wins afterward
    available: ["light", "dark", "nord"], // selector entries — all 35 daisyUI themes are bundled
    custom: [                            // your own theme, no build step (root-only in multi-spec)
      { name: "acme", extends: "dark", tokens: { "--color-primary": "#7c3aed" } }
    ]
  },
  language: {
    default: "browser",                  // follows the browser's languages; or pin a code
    available: ["en", "fr"]              // non-active languages download on demand
  },
  environments: [                        // pre-filled on first load; the reader's storage then wins
    {
      name: "sandbox",
      color: "green",                    // red flags production at a glance
      baseUrl: "https://sandbox.example.com",
      variables: { "auth.bearerAuth": { value: "demo-token", sensitive: true } },
      defaultHeaders: { "X-Client": "docs" }
    }
  ],
  environmentsLocked: false,             // true removes every create/edit entry point
  docsPages: [                           // your markdown guides, woven into the nav
    { slug: "getting-started", title: "Getting started", url: "/docs/getting-started.md" },
    { slug: "changelog", title: "Changelog", url: "/docs/changelog.md", kind: "changelog" },
    // nav: "bottom" sends a top-level entry to the appendix zone, below the reference.
    { slug: "support", title: "Support", url: "/docs/support.md", nav: "bottom" }
  ],
  feedback: {
    url: null                            // your endpoint for "Was this page helpful?" — null removes the row
  },
  scenarios: [                           // executable scenarios shipped with the docs
    { id: "first-order", title: "Order a pet", url: "/scenarios/first-order.json", pinned: true }
  ],
  features: {
    scenarios: true,                     // false removes the whole feature
    audit: true,                         // false removes the schema audit
    onboarding: false,                   // true adds the generated "First call" page (#/first-call)
    ci: true                             // false removes the "Automate this scenario" panel
  },
  branding: {
    productName: "Acme API",             // header name
    logoUrl: "/logo.svg",                // header logo
    footerLinks: [{ label: "Status", url: "https://status.example.com" }]
  },
  tryIt: {
    proxyUrl: null,                      // optional CORS proxy you host — "{{target}}" = encoded target URL
    requestCredentials: "same-origin"    // "include" for cross-origin session-cookie auth
  },
  history: {
    maxEntries: 500,                     // purge beyond this count…
    maxAgeDays: 30                       // …or this age (root-only in multi-spec)
  },
  oauth: {
    // Key = the scheme's name in securitySchemes. Never a client secret.
    acme_auth: { clientId: "public-client-id" }
  },
  seo: {
    index: true                          // false injects a robots noindex before first paint (root-only)
  }
}

openapi

KeyWhat it does
openapi.urlURL of the OpenAPI 3.0.x–3.2.x schema, JSON or YAML. The hosting server must allow cross-origin reads (CORS).
openapi.specThe schema itself — JS object or JSON string — carried by the page: no request, no CORS. Wins over url.
openapi.specsSeveral schemas in one installation: [{ id, title, url }] entries, almost every key overridable per entry. Wins over url. See the multi-spec guide.
openapi.defaultThe spec shown on arrival in multi-spec (first entry otherwise).
openapi.hidePatterns removing operations from nav, search and exports: "tag:Internal", "DELETE /admin/*", "/admin/*", "resetDatabase" (operationId — the fallback id {method}-{path-slug} matches too). Documentation hiding, not security — the browser still downloads the full schema. See OpenAPI support & schema control.
openapi.overlaysOpenAPI Overlay 1.1 documents (URL or inline object) applied to the schema at load, in declaration order. Failed actions are reported, never silent. Full semantics in the schema guide.
openapi.userOverlayA starting patch seeded into the reader’s own overlay editor (default null). Per spec it replaces the root’s document rather than stacking, and re-seeding a different document discards the reader’s local edits.

theme

KeyDefaultWhat it does
theme.default"system"Theme applied on first load; the reader’s persisted choice then takes priority. "system" follows the OS prefers-color-scheme within the first light/dark pair of available.
theme.available["apiglow", "apiglow-dark"]Themes offered in the selector — the default is the app’s signature pair. All 35 standard daisyUI themes are bundled, so listing one costs nothing.
theme.customYour own themes, generated at boot from daisyUI tokens — no build step. Root-only in multi-spec. See the theming guide.

language

KeyDefaultWhat it does
language.default"browser"UI language on first load: "browser" follows the reader’s navigator.languages within available; a language code pins it. The reader’s persisted preference wins afterward.
language.availableLanguages offered. English ships in the bundle; the others download on demand.

Environments

KeyDefaultWhat it does
environments[]Environments pre-filled on first load: { name, baseUrl, variables, defaultHeaders }. A variable is { value, sensitive }; sensitive ones are masked on display and redacted in history and exports. After first load, the reader’s own storage is authoritative.
environmentsLockedfalsetrue removes every UI entry point to create or edit environments — only the selector remains. For controlled corporate deployments.

Content: docsPages, feedback and scenarios

KeyDefaultWhat it does
docsPages[]Prose pages woven into the nav: { slug, title, url } — or content (the text itself) or contentId (id of a non-executable script element in the host page) instead of url. Add kind: "changelog" to render a page’s h2 headings as a release timeline; nav: "bottom" on a top-level entry sends it to the appendix zone below the API reference. Groups, external links, per-language maps, a home: true takeover and a JSON-manifest URL form are all covered in the docs pages guide.
feedback.urlnullYour endpoint for the “Was this page helpful?” row on docs pages, which POSTs { "page": "<slug>", "verdict": "up" | "down" } as JSON. No URL, no row — the app never sends anything anywhere on its own. Cross-origin, the JSON content type makes it a preflighted request. Overridable per spec.
scenarios[]Scenarios shipped with the docs: { id, title, url } pointing at exported files; pinned: true features one on the home page. In multi-spec, declared only on specs[] entries. See authoring scenarios.

features

KeyDefaultWhat it does
features.scenariostruefalse removes the scenarios feature entirely — nav, capture buttons, routes, search index. Stored local scenarios survive, intact, for when it is re-enabled.
features.audittruefalse removes the schema audit: the settings block, the #/audit route, every computation.
features.onboardingfalsetrue adds a generated “First call” page (#/first-call) at the top of the reference nav: the simplest GET the schema declares, walked through in the real try-it — language, credentials, Send. Absent when the schema declares no such read. See Auth & onboarding.
features.citruefalse removes the “Automate this scenario” panel — the CI hand-off. The Arazzo export in the scenario menu stays.

branding

KeyDefaultWhat it does
branding.productNameName shown in the header.
branding.logoUrlnullURL of a logo shown in the header.
branding.footerLinks[]Your links in the footer bar: [{ label, url }]. The bar itself stays — the About dialog carries the license notices a CDN install ships no file for.

tryIt

KeyDefaultWhat it does
tryIt.proxyUrlnullOptional CORS proxy template, {{target}} = encoded target URL. The app ships no proxy — you host it.
tryIt.requestCredentials"same-origin"Credentials mode of the try-it’s fetches: "omit", "same-origin" or "include". "include" is required for cross-origin session-cookie auth, with server-side constraints detailed in Try-it & CORS.

history

KeyDefaultWhat it does
history.maxEntries500Purge the request history beyond this count (whichever threshold hits first).
history.maxAgeDays30…or beyond this age. Root-only: retention is a browser storage cap, shared by all specs.

oauth

KeyDefaultWhat it does
oauth{}Per OAuth2 scheme (key = its name in securitySchemes): { clientId } used by the in-browser flows, overridable by the auth.X.clientId environment variable. Never a client secret — the host page is public.

seo

KeyDefaultWhat it does
seo.indextruefalse injects <meta name="robots" content="noindex"> before first paint. Root-only: one page is served at one URL, and a crawler reads it without choosing a spec. A request to well-behaved crawlers, not a protection — and the bake CLI refuses to run on a noindex config. Pair with an X-Robots-Tag header for non-HTML files; never with a robots.txt Disallow.

One capability deliberately has no key at all: host-provided credentials are a runtime-only API (window.apidoc), so a token can never end up written in the config — see the host credentials bridge. A reader’s local schema patch is nearly as private: openapi.userOverlay can seed its opening state, but there is no flag to disable it, because it changes one browser’s view of the document and your hide rules still apply after it.

Per-spec overrides (multi-spec)

In an openapi.specs[] installation, the root config is the fallback and nearly every key can be redeclared on an entry. Four rules decide the merge:

  • Settings objects (tryIt, branding, theme, language, features, oauth) merge key by key, the spec wins — a key declared at null wins too, so a spec can disable the root proxy.
  • Named lists (docsPages by slug, environments by name) merge by identifier, the spec wins.
  • hide and overlays accumulate — hiding cannot be un-hidden, and overlays apply root first, then the entry’s own.
  • environmentsLocked is replaced when declared.

Four exceptions, each flagged by name in the console when a config gets them wrong: history is root-only, theme.custom is root-only (themes are global chrome, injected once at boot), seo is root-only (indexability describes the served page, which all specs share), and scenarios go the other way — declared only on specs[] entries, because a scenario references operations of one specific spec.