---
title: Scalar
description: Embed Scalar's self-contained API reference UI on a single route, with any Scalar option passed straight through.
---

Blume's own renderer is what [`openapi()`](/docs/references/openapi), [`asyncapi()`](/docs/references/asyncapi), and [`graphql()`](/docs/references/graphql) give you: one real page per operation, in your sidebar, search, and `llms.txt`, with a [Try it playground](/docs/references/openapi#try-it-playground). If you'd rather embed [Scalar](https://scalar.com)'s self-contained API reference UI — its own sidebar, search, theme, and request client on a single route — list a `scalar()` adapter from `blume/reference` instead. It takes an OpenAPI or AsyncAPI document and Scalar detects which:

```ts blume.config.ts lineNumbers
import { defineConfig } from "blume";
import { scalar } from "blume/reference";

export default defineConfig({
  reference: [
    scalar({
      spec: "./openapi.yaml",
      theme: "purple", // a Scalar theme name
    }),
  ],
});
```

That mounts the embed at `/reference`. `spec` is either an `http(s)` URL, which the page loads from the browser, or a path to a local file, which is read at build time and inlined so the page stays self-contained. `route` moves it, and `sources` publishes several documents, each on its own route — the same [`label`/`route` rules](/docs/references/openapi#multiple-specs) the native adapters follow:

```ts blume.config.ts lineNumbers
reference: [
  scalar({
    route: "/api",
    sources: [
      { label: "Public API", spec: "./public.json" },   // → /api/public-api
      { label: "Legacy API", route: "/legacy", spec: "./legacy.json", noindex: true },
    ],
  }),
],
```

A Scalar embed and native pages can sit side by side in the list — an `openapi()` adapter for the current API and a `scalar()` adapter for a legacy one, say — as long as their routes differ. Like every reference, the embed doesn't add a header tab on its own; point a [navigation tab](/docs/content/navigation#tabs) at its route to surface it.

## What the embed doesn't do

A Scalar-rendered reference is a self-contained page on its own route. It doesn't weave into Blume's sidebar, search, or `llms.txt`, so of the native adapters' per-source controls only `noindex` applies here (it adds crawler noindex metadata and keeps the page out of the sitemap); there is no `codeSamples`, `expandSchemas`, or `playground` to set. Scalar brings its own request client, which calls your **target API directly from the browser** (Blume's [`playground.proxy`](/docs/references/openapi#cors-and-the-proxy) route isn't available here), so the API must allow cross-origin requests from the docs site (`Access-Control-Allow-Origin`).

The embed does follow Blume's light/dark toggle: it's pinned to the page's theme when it mounts and switches with it, so Scalar's own theme switch is hidden (pass `forceDarkModeState` or `darkMode` to hand color mode back to Scalar). Without a `theme`, Blume layers its accent and radius onto Scalar's default theme; a named `theme` replaces that. The adapter declares `@scalar/astro` as its runtime dependency, so the generated project only lists it when a `scalar()` adapter is configured.

## Passing Scalar options

`theme` is the one option most people reach for, but Scalar supports many more. Every key you pass to `scalar()` beyond `spec`, `sources`, `route`, and `theme` is forwarded verbatim as [Scalar configuration](https://github.com/scalar/scalar/blob/main/documentation/configuration.md) to the embedded reference — Blume doesn't gate the keys, so anything Scalar accepts flows through (JSON values only, since the configuration is inlined into the generated page):

```ts blume.config.ts lineNumbers
reference: [
  scalar({
    spec: "./openapi.yaml",
    localization: { locale: "es" },   // translate Scalar's own UI
    agent: { disabled: true },         // disable the Scalar Agent
    hideTestRequestButton: true,
    orderSchemaPropertiesBy: "preserve",
  }),
],
```

Blume's own [`i18n`](/docs/content/i18n) translates the docs chrome, but Scalar has a separate localization system — set `localization.locale` to translate the embedded reference too. Forwarded options win over Blume's derived config, so anything set here (including `customCss` or the spec `content`/`url`) overrides Blume's defaults. The one key that can't be forwarded is Scalar's own multi-document `sources`: that name is Blume's, and each Blume source becomes its own page.

## AsyncAPI documents

Point `spec` at an AsyncAPI document and the embed renders channels, operations, messages, and a Models section. Scalar has no AsyncAPI playground of its own, so choosing the embed over [`asyncapi()`](/docs/references/asyncapi) trades Blume's [event composer](/docs/references/asyncapi#try-it-for-events) away. A GraphQL schema has no Scalar embed at all — the [`graphql()`](/docs/references/graphql) reference is always rendered natively.
