NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
Generate beautiful API references from OpenAPI documents
Last release today
12 Oct 2026
Ships on a steady schedule
a new release about every 2 weeks
Most releases are documented
notes for 50 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
3 years old
719 releases · first in 2023
One column per quarter.
Show channel messages only when they are not used by an operation, and keep the sidebar in sync.
mcp.disabled keep their current footer. Adds exploreScalar translations to ApiReferenceTranslations and a startViewTransition helper to @scalar/helpers/dom.#10554: Render AsyncAPI boolean schemas with explanations in message payloads, headers, and reusable models.
#10570: Keep AsyncAPI messages searchable when their rendered anchors belong to operations, while deduplicating messages referenced by multiple operations.
#10527: Document every visible AsyncAPI channel message in a channel catalog while preserving operation-specific message subsets, links, and server/protocol filtering.
#10565: Inherit AsyncAPI operation metadata and replies from traits using recursive merge rules, and use inherited titles in navigation.
#10545: Convert flow-style YAML documents to valid JSON when downloading in JSON format.
#10509: Remove a redundant assignment in SDK installation tab keyboard navigation.
#10529: Display AsyncAPI server titles, summaries, and protocol versions while preserving server map keys for selection.
#10550: Display AsyncAPI message correlation ID descriptions and runtime expressions, with links to identifiable header and payload fields.
#10513: Document browser-loaded plugins with NestJS and add a custom extension example.
#10534: feat(api-reference): add Generate SDK buttons to the developer tools, client libraries and request examples that open the Explore Scalar dialog when running locally and the document does not list its own SDKs
#10506: Organize imports consistently with the checks enforced in CI.
#10558: Fix AsyncAPI example cards to use the full available width, keep only the code block copy button, and pad and align the example name and summary.
#10525: Display the AsyncAPI application identifier in the introduction when present.
#10566: Render inline AsyncAPI security schemes and scopes, keeping server authentication separate from operation security.
#10573: Hide the empty Operations card for parent tags that only contain nested tags. Tags with their own operations or webhooks still show their endpoint list.
#10528: Render AsyncAPI channels and their messages when no operations reference them, including server and protocol filtering.
#10561: Clarify AsyncAPI operation and message sections, align message card spacing, and keep schema controls inside lighter expanded cards.
Show channel messages only when they are not used by an operation, and keep the sidebar in sync.
#10511: Expose an actions slot on Tag to add custom header controls in modern and classic layouts.
#10508: Add built-in Traditional Chinese (Taiwan) translations for zh-TW, including case and underscore variants, across API Reference, API Client, and schema blocks.
### Patch Changes - #10481: Show AsyncAPI external documentation links in introductions, including references, and preserve root external documentatio
#backdrop slot on ScalarDropdown, ScalarPopover, ScalarListbox, and ScalarCombobox is removed; style the floating element with class instead. ScalarFloatingBackdrop, --scalar-lifted-brightness, and the brightness-lifted utility are deprecated in favor of bg-b-1 dark:bg-b-1.5. ScalarFloatingBackdrop itself now uses the same surface styles, so it no longer clips its slot or draws a real border. A new inset-shadow-border utility draws the hairline border so it can stack with shadow-* without taking up layout space; Tailwind's default inset-shadow-* sizes are reset, matching the other theme namespaces.Keep the public API Reference Schema and SchemaProperty exports connected to extension plugins and deep-link navigation when mounted outside ApiRefere
featuredClients to choose which clients are shown as tabs in the "Client Libraries" block, and in which order.hideModelNames to show structural types instead of model names in schema type labels and operation headings.maxVisibleRequestBodyProperties to control the initial request body property limit (default 12, or 0 for unlimited) independently of nested schema expansion. Show the number of hidden properties in the overflow control.#10462: Keep nested allOf object fields and choice groups inside their named property. Recursive references render as leaves without repeating composition choices.
#10452: Autofill the OAuth2 redirect URL on initial load when configured authentication flows have no scopes.
#10468: Stop the schema property copy-link button from taking width from a collapsed preview such as { compound, percentage }. Its 24px hit box now overhangs the end of the line, so the row gives up only the icon and its gap, however the consuming app orders its stylesheets.
#10397: Extract the schema renderer into @scalar/blocks so other Scalar surfaces can reuse the schema tree while preserving API Reference behavior.
Keep the public API Reference Schema and SchemaProperty exports connected to extension plugins and deep-link navigation when mounted outside ApiReference.
Expose shared presentation components through @scalar/blocks/shared, group host integration APIs under schema/helpers and schema/expansion, and keep schema stories and visual regression coverage with Blocks.
Preserve literal toolbar icon types so Storybook previews can be type checked.
Pass schema navigation, extension rendering, and shared expansion state explicitly through props instead of providing or injecting host context.
#10448: Expose an actions slot on the Operation component to replace its default copy control in embedded layouts.
#10441: Truncate long composition picker labels while keeping the full text available on hover and in the dropdown.
#10467: Use the design system border, shadow, and extra-large radius for all floating surfaces. Backdrops now inherit their radius from the floating element, and the lifted brightness no longer brightens the border.
The code block scroller is exposed as a named group ("Code sample: Shell cURL" in the API Reference, localizable via operation.codeSample) so screen r
#10372: fix: improve keyboard and screen reader access to code blocks and multiselect comboboxes
operation.codeSample) so screen readers announce it when it receives focus#10437: Stop a discriminator oneOf variant that composes its base with allOf from rendering a second selector, its fields twice, or a repeated variant description.
#10439: Fix missing chunks after a release when a cached ESM entry point is loaded from an unversioned npm CDN URL. The generated loader selects its own exact release using a relative package URL, preserving the CDN hostname and path prefix. This supports jsDelivr, UNPKG, and other hosts with versioned npm package paths while keeping latest as the default. Custom self-hosted paths continue loading the bundle next to the entry point.
### Patch Changes - #10421: Collect schema search fields in one traversal and reuse extraction within each search index build. - #10422: Avoid computi
Deprecated schema rows no longer fade their contents to 75% opacity, which had dropped their muted text to 3.0:1. The diagonal stripes, the strikethro…
#10369: fix: correct the semantics of the authentication card and of nested schema lists
Two findings from an accessibility audit, both programmatic only with no change to how anything renders:
#10364: Prevent repeated introduction fragments when reopening API descriptions that start with a Markdown heading.
#10375: Raise muted text, code-string blue and the deprecated schema row to the 4.5:1 text contrast minimum across the shipped themes
An accessibility audit turned up text that is legible in the default theme but not in several of the presets, which pair the default greys and blues with an off-white page background. Nine presets and four integration themes get a hue-preserving nudge:
--scalar-color-2 now clears 4.5:1 on both the page background and the grey card background in every preset. That covers alternate, bluePlanet, mars and saturn, which paired the default grey with an off-white page, and custom-theme-starter, deepSpace, elysiajs, fastify, kepler and purple, which copied the default grey and were left behind when the default moved.--scalar-color-blue, which colours code strings, now clears 4.5:1 on the grey example background in alternate, bluePlanet, deepSpace, elysiajs, fastify, kepler and moon, and in the Docusaurus, NestJS, Next.js and SvelteKit themes.--scalar-color-blue now clears 4.5:1 in purple and saturn, and in the Hono and Docusaurus dark themes.laserwave.--scalar-focus-color sits further from the accent so a keyboard focus ring clears 3:1 on --scalar-background-3 as well, which some presets use for the selected sidebar item.laserwave still misses in light mode, where it reuses its dark accents unchanged; bringing it up is a redesign of the preset rather than a nudge.
#10385: feat: add UTM parameters identifying the integration to the "Powered by Scalar" link
#10375: fix: raise text and focus ring contrast flagged by an accessibility audit
The default light blue is a touch deeper so code strings and read-only labels meet 4.5:1, the required label darkens in light mode, keyboard focus rings now draw from a new --scalar-focus-color token that meets 3:1 against hovered and selected surfaces, and the schema union pipe, Default, Example and Pattern labels use the regular muted text colour.
#10373: fix(api-reference): correct selected state, focus ring, target size and reflow of reference controls
Rename the always-present layout container class and CSS container name from narrow-references-container to references-container.
#10369: fix: address a batch of screen reader and keyboard accessibility findings
Corrects programmatic semantics only, with no change to how anything renders:
the current sidebar item now reports aria-current, the single content type
readout leaves the tab order, collapsible sections no longer announce their
title twice, the password toggle reports its state through aria-pressed, the
two document download buttons get distinct accessible names, response status
tabs announce what each code means, and the client picker and its search field
get accessible names.
#10379: fix: remove the duplicate copy button from the example response header
The response card carried its own copy button in the tab strip, added in 2023 when the card had no other copy affordance. The code block inside it later gained a built-in copy button of its own, which left every response card showing two buttons that copy the same content. Only the code block's button remains.
#10388: Prevent Safari from outlining an entire operation section after sidebar navigation while preserving focus on the navigation target.
Generate XML examples from schema metadata, preserving attributes, namespaces, array wrappers, repeated elements, and OpenAPI 3.2 text and CDATA nodes
#10192: Mock-server XML response bytes now use the shared schema-aware serializer instead of json2xml, including attributes, namespaces, and root naming. Existing XML response snapshots may need updating. Supplied serialized XML remains unchanged.
Generate XML examples from schema metadata, preserving attributes, namespaces, array wrappers, repeated elements, and OpenAPI 3.2 text and CDATA nodes. Use the same XML serialization for request bodies, code snippets, response examples, mock responses, and Markdown documentation. Preserve serialized media examples and escape schema string examples as element text.
Explain XML generation failures in response example panels, including the serialized-example escape hatch for large payloads. Expose XML generation failures in mock response headers with X-Scalar-XML-Error, containing the first error diagnostic code. Report diagnostics to other consumers through a callback or the developer console, and format element-only descendants within mixed content without changing text values.
#10335: Clarify operation authentication tooltips with separate headings, readable scheme types, API key locations and names, and formatted descriptions.
#10336: Preserve nested object boundaries for properties composed from multiple allOf schemas.
#10333: Fix sidebar navigation scrolling past operations and models in themes with decorative backgrounds.
Measure only headers registered with data-scalar-scroll-header when scrolling to content. Scalar registers its mobile header and sticky breadcrumb bar automatically; embedding sites can register their own fixed or sticky headers with the same attribute.
Host headers are no longer discovered automatically. Register fixed or sticky host headers with data-scalar-scroll-header, or reserve their height with --scalar-custom-header-height. Registered Scalar breadcrumbs are counted below that reserved space.
Non-form whole-query content, including JSON delimiters, is percent-encoded in request URLs and code samples. Use an example with serializedValue on t
#10189: Support OpenAPI 3.2 in: querystring parameters, including content-based serialization, editing the entire query string, schema rendering, and generated request URLs.
Non-form whole-query content, including JSON delimiters, is percent-encoded in request URLs and code samples. Use an example with serializedValue on the parameter itself for URI-ready query content that must retain its existing encoding.
Preserve the encoding of named query values when they coexist with whole-query content in generated code samples, while encoding query authentication values once.
Explain why the whole-query editor disables adding named parameters. Existing named parameters follow the whole-query value, preserving duplicate keys for the server to interpret.
#10186: Support OpenAPI 3.2 additionalOperations in operation storage, navigation, documentation, callbacks, and the API client. Preserve custom HTTP method spelling when displaying and sending requests and generating code samples.
Traversed operation and webhook methods now use the exported OperationMethod type, which accepts custom strings while retaining known-method editor completion. Consumers must handle unknown methods; this open type cannot provide exhaustive checking over the fixed HTTP method set. Unknown method presentation uses colorClass and colorVar, matching known methods. Preserve uppercase and mixed-case additional operation names consistently.
#10313: Render the accordion header's title and actions beside the toggle button instead of inside it. A button start tag inside an open button implies the end tag for the outer one, so the copy-link button in an AsyncAPI message heading (and the controls in an operation's header) were re-parented by the HTML parser and server-rendered sections could never hydrate. Clicking the header text or caret still toggles the section, while the copy-link and action buttons keep their own behavior.
#10186: Preserve authored method variants in request data and navigation links. Generate custom-method requests with generic client APIs, and explain when RestSharp cannot represent a method.
#10186: Support document-defined additional operations in Markdown operation, webhook, and tag selections. Preserve custom method spelling and inherited parameters, servers, and security when copying an operation as Markdown.
#10322: Use OpenAPI 3.2 dataValue and serializedValue examples for named parameters in the editor, outgoing requests, and code samples. Preserve already serialized values without encoding them twice.
Optional parameters with dataValue or serializedValue examples are now enabled by default, matching legacy value examples. Explicitly disabled examples remain disabled.
Parameter-level serializedValue examples remain editable as raw wire text, including parameter names and percent encoding (for example, term=hello rather than hello). Media-level cookie examples are percent-encoded when sent, matching generated snippets. Generating snippets no longer modifies the input cookies.
#10317: Show discriminator mapping values beside schema names in oneOf and anyOf selectors.
#10313: Keep the introduction selected in the sidebar while the top of the document is in view. The sentinel at the start of the document and every description heading observe their own intersections, and the browser delivers those first records in no fixed order, so a server-rendered page could settle on whichever heading arrived last. The selection is now resolved from the sentinel's position instead of the order the events arrive in.
#10310: Connect SDK code samples to named request body examples using optional example and contentType fields. Keep the example switcher available for static samples and use the selected request example in API client snippets. Display unavailable linked samples as a localized status message in all supported languages.
Preserve generated falsy request examples (0, false, and empty strings) for non-streaming bodies as well.
#10222: Add a Copy as Markdown button to operations and webhooks in both API Reference layouts. Add a browser entry point for converting resolved OpenAPI documents to Markdown.
#10283: Add expandAllParameters, defaulting to true. Set it to false to start operation parameters collapsed and expand each parameter on click.
#10178: Support OpenAPI 3.2 streaming item schemas in the workspace store, request body examples, and API reference schema views. Frame generated and structured examples as JSON Lines, JSON Sequence, or server-sent events while preserving explicit wire-format strings.
Preserve generated falsy request examples (0, false, and empty strings) for non-streaming bodies as well.
Use cURL --data-binary for supported streaming media types, making framed body handling explicit. Authored arrays and objects are framed as stream records; authored wire-format strings remain unchanged. SSE records with no valid fields are safely omitted with one console warning per serialization call reporting the omitted count, including when all records are omitted.
#10300: fix(api-reference): pick badge text color from the background's lightness
A colored x-badges entry used a darker shade of its own background as text, which is muddy on mid-tone colors and only mid-gray on pale ones. The text is now black on light backgrounds and white on dark ones, derived in CSS from the background's lightness, so every color format works. Browsers without relative color syntax keep the previous shading.
#10177: Use OpenAPI 3.2 schemas throughout workspace-store consumers, stories, tests, and type generation. Update the app editor to offer OpenAPI 3.2 validation and completion while continuing to accept existing 3.1 documents.
Preserve OpenAPI 3.2 fields in the loose workspace schema, including tag hierarchy, streaming media types, nested encoding, additional operations, and OAuth device authorization.
The editor intentionally offers the 3.2 field set to documents declaring 3.1 as well; it does not flag 3.2-only fields solely because the declared version is 3.1. This does not certify conformance to the declared version or automatically update it. Before using 3.2-only fields, migrate and explicitly declare OpenAPI 3.2, and verify support in other validators and generators. Remove the unused 3.1 loose-schema generator to prevent schema drift.
Migration: the OpenAPI 3.1 loose-schema generator (@scalar/workspace-store/schemas/v3.1/openapi, published through the wildcard as @scalar/workspace-store/schemas/v3.1/openapi/index) and its @scalar/workspace-store/schemas/v3.1/openapi/reference helpers have been removed. Import the generator from @scalar/workspace-store/schemas/v3.2/openapi/index and the reference helpers from @scalar/workspace-store/schemas/v3.2/openapi/reference instead. The ./schemas/* wildcard and the 3.1 strict-schema exports remain available; the explicit 3.2 strict-schema exports are additive. Locally generated types now use the OpenAPIV3_2 namespace instead of OpenAPIV3_1.
Inline the editor path-extension reference so Monaco retains the leading-slash path pattern and does not report valid paths as unknown properties.
Document ingestion continues to upgrade only to OpenAPI 3.1, so existing inline XML bodies without xml.name remain loadable. This schema migration does not opt consumers into the stricter OpenAPI 3.2 XML upgrade.
#10203: Add a picker for generated response examples with anyOf or oneOf schema variants.
Apply union selections to primitive and array examples in the shared generator without reusing the selection for nested unions.
The shared generator change also affects request examples, snippets, mock responses, and AsyncAPI payloads: root primitive/array unions now generate their chosen branch before type inference from sibling properties or items. For example, a string schema with oneOf: [{ const: "first" }, { const: "second" }] now generates "first" by default, and selecting the second branch generates "second". Keywords for unrelated types do not force object/array generation. Root selections are consumed once; nested unions retain their own default or path-specific choice.
Do not show a response variant picker for an empty enum, which permits no valid alternatives.
Preserve the generated branch shape in mock HTTP responses instead of re-wrapping selected primitive values as arrays based on root sibling items. Explicit authored examples retain the existing array normalization.
#10287: Load the agent drawer and chat when first opened instead of when the agent is enabled. Keep the conversation mounted when closing and reopening.
#10284: Load the API client modal on its first open request instead of downloading it when the API reference or agent chat mounts. Preserve the requested operation, example, and request-body variant while loading. Show loading feedback and retry guidance if the request editor cannot be downloaded.
#10175: Support API Client UI translations through localization.translations.apiClient, including the client embedded in API Reference. Ship client translations for English, Russian, Spanish, French, German, Simplified Chinese, Arabic, and Portuguese to match API Reference. Preserve English fallbacks across package providers and react to locale, direction, and translation updates.
#10212: Improve type safety for schema display metadata, schema property merging, deprecated configuration migration, and cyclic test fixtures. Load Vite declarations for raw playground imports.
#10208: Share OpenAPI 3.2 example-value selection across request bodies, response examples, and code snippets. Preserve serialized payloads verbatim, serialize structured JSON strings correctly, retain falsy values, and replace original example sources after body edits. Keep dataValue and serializedValue during document ingestion.
Editing a request body, including form fields, discards its authored externalValue URL and replaces it with the edited inline value in the workspace and exported API description. Rendering or focusing a form field preserves the external source.
Form editors prefer structured dataValue when both example fields exist, while raw editors, requests, and code snippets preserve serializedValue as wire text. Structured examples now affect generated request payloads and snippets; XML remains raw-only in the request editor.
Preserve sibling keywords when merging nested allOf properties. Display an explanation when enum constraints allow no values, and omit empty enum anno
#10217: Generate AsyncAPI payload examples from JSON Schema when no explicit payload example is provided. Preserve literal proto keys when cloning example data.
#10253: Keep deep-linked headings visible below sticky or fixed headers, including stacked navigation bars. Preserve scrolling inside embedded containers and existing scroll margins, and exclude sidebars beside the target from the header offset.
#10240: Load external examples on demand when their selected preview is visible or Test Request opens, instead of downloading every payload while loading the API description. Share and cache downloads, preserve relative URL origins, and show loading and retry states while preventing incomplete requests from being sent.
#10249: Show response example summaries and descriptions alongside their payloads.
#10232: Intersect enum values when merging allOf schemas so inherited properties show only allowed values.
Preserve sibling keywords when merging nested allOf properties. Display an explanation when enum constraints allow no values, and omit empty enum annotations.
Nothing published for this version
For local development, Scalar deliberately relaxes the OpenAPI 3.2 TLS requirement: metadata URLs and discovered endpoints may use HTTP for local deve
#10229: Fix the API client modal getting stuck on "Select an operation to view details" for a document's first operation after its active document re-syncs. The reference used to hand the modal a route to a nonexistent path and method during that re-sync; the modal now leaves the current operation in place instead.
#10237: Use document environment defaults in API references and the Test Request client so template variables resolve correctly.
#10179: Support OpenAPI 3.2 OAuth2 metadata URLs in workspace schemas and the shared authentication UI. Fetch HTTPS authorization server metadata or HTTP metadata from local development URLs to discover flows or fill missing endpoints while preserving explicit configuration.
For local development, Scalar deliberately relaxes the OpenAPI 3.2 TLS requirement: metadata URLs and discovered endpoints may use HTTP for local development URLs recognized by the shared isLocalUrl helper, including loopback hosts, 0.0.0.0, and reserved development domains such as *.test and *.example. Other hosts require HTTPS.
Discovery leaves refreshUrl unchanged. Token refresh already falls back to the flow's token URL when no refresh URL is configured, so a discovered token endpoint also supports refresh without overriding an explicit refresh URL.
#9852: Render OpenAPI 3.2 response summaries, server names in the server selectors, and a strikethrough on deprecated security schemes.
ScreenReader moves off the deprecated clip property to clip-path and adds white-space: nowrap, so multi-word announcements are no longer split at wrap…
#9675: feat: move schema-vocabulary translation keys from common.* into schema.* and drive localization through the new shared @scalar/localization engine.
If you customize localization.translations, schema-related keys have moved namespace — for example common.nullable is now schema.nullable and common.required is now schema.required. Only description, httpMethod, and path remain under common.
#10126: refactor(api-reference): remove the legacy schema layout and the schemaLayout option
The legacy schema layout — a bordered card per nesting level behind a "Show Child Attributes" pill — is deleted, together with the schemaLayout configuration option that selected it. The tree layout is the only schema renderer.
The schemaLayout option never shipped in a release, so there is no schemaLayout value to remove from your configuration. Five translation keys the deleted markup owned are removed from ApiReferenceTranslations, and therefore from the ApiReferenceTranslationKey union: schema.childAttributes, schema.hideChildAttributes, schema.showChildAttributes, operation.hideHeaders and operation.showHeaders. They labelled the "Show Child Attributes" pill and the headers disclosure toggle, neither of which renders any more. If you override any of them in localization.translations, delete those entries — TypeScript will otherwise report an unknown-property error on the object literal.
The class names the tree already carried (.schema-card, .property, .property--level-N and their family) are unchanged, so customCss keeps working.
#10074: feat(api-reference)!: the tree layout is the schema renderer
The tree layout is the schema renderer, so every visual baseline that renders a schema changes with this release and is regenerated per suite.
#10074: feat(api-reference): lift schema expansion into a store so deep links and expand-all work at runtime
Expansion state used to live inside Headless UI's <Disclosure>, which reads defaultOpen once at mount and offers no controlled mode. That single fact is why a second deep link into an already-rendered operation silently did nothing, why a runtime expand-all could not exist, and why switching a oneOf variant threw away everything the reader had opened.
The schema tree now owns its own disclosure and resolves each node against a per-reference store: an explicit choice by the reader wins, then the nearest expand-all or collapse-all, then the standing baseline, then a live deep link, then whatever the node would have done on its own. Bulk actions clear the overrides beneath their own root first, so "Expand all" no longer skips every node the reader has touched. Cyclic nodes opt out of bulk expansion and the baseline, which is what stops a self-referential schema expanding forever.
Following a deep link now moves focus to the target as well as scrolling to it, and writes the path it opened into the store, so the expansion is permanent and collapsible rather than evaporating when the scroll target clears. Collapsing a subtree that contains the focused element moves focus up to that row's toggle instead of dropping it to the document body.
Model properties gain anchors: the models layout now passes a breadcrumb, which it never did while the operation layout always has.
Response header anchors no longer carry a doubled headers.headers path segment, and are now qualified by status code so each response's headers are addressable on their own. An anchor of the old shape carried no status code, so it cannot be translated; following one now scrolls to the operation it belongs to instead of failing silently.
The store is created per <ApiReference> rather than module-global, so two references on one page do not share expansion. Markup, class names and layout are unchanged; the generated id and aria-controls values on schema disclosures differ, since they no longer come from Headless UI.
#10074: feat(api-reference): the tree schema layout
The tree layout replaces the bordered card per nesting level and the "Show Child Attributes" pill with the visual grammar of a tree: a continuous rail per depth that hangs from the parent property's text column, and a discrete disclosure control in each expandable property's own gutter. The control is a real button whose accessible name is the property name alone and whose child count rides aria-describedby; property descriptions stay visible instead of being swallowed into a button label. Types render as token runs — array of Planet instead of array Planet[], with a $ref link as the type itself — collapsed objects show a preview of what they hold, short enums render inline in the type position or wrap as chips instead of a row per value, and a $ref cycle says recursive in its own signature line instead of offering a toggle that descends forever. Rails fade with depth, capped so the deepest ones never wash out into the page. In a narrow container — the same max-width: 900px query the sections already use — the indent tightens and the controls shrink, so a deep tree still fits and the outermost control clears the page edge instead of being clipped by it. Collapsed subtrees that were opened once stay reachable with find-in-page via hidden="until-found" where the engine supports it, against a budget shared by every tree in the reference, with Safari falling back to unmounting exactly as before.
Printing temporarily expands the whole tree and restores the reader's expansion state afterwards.
#10074: feat(api-reference): one disclosure grammar across every surface in the tree layout
The tree layout now reaches the surfaces the schema renderer never covered. Response headers fold into the tree as a child group named Headers, keyed into the expansion store so expand-all and deep links finally reach them — and the headers card's long-standing CSS syntax error is fixed along the way. Callbacks trade their native details/summary for the gutter control, and gain breadcrumbs, so a property inside a callback body is addressable for the first time. AsyncAPI message headers and payloads gain breadcrumbs the same way. Parameter rows keep rendering their type, required marker and description inline: a disclosure may hide child elements, never child information, and the classic layout starts passing collapsableItems — previously omitted, which silently made expandAllResponses a no-op there. Model properties in the classic layout gain anchors.
Group titles — Body, Responses, Query Parameters, Callbacks — become real headings through the document outline (operationSection, level 4), never hardcoded tags.
One flagged feature ships with this: schemaKeyboardNav (default off) adds APG-tree arrow-key navigation over the gutter toggles.
#10102: Allow response hooks to return a replacement Response before the client processes its body, status, and headers. Add the onResponseReceived configuration callback for API References. Existing hooks can still read responses and return nothing.
#10171: Show AsyncAPI message examples with a picker and copy button. Disambiguate generated labels that collide with authored example names.
#10157: Match SDK installation code blocks to the default client library rendering
#10125: Preserve multiple sources supplied through the standalone data-configuration attribute
#10143: Stop rendering a discriminator base property twice. When a property's schema is a bare discriminator.mapping base (an object with properties and a discriminator but no explicit oneOf/anyOf), the inferred variant selector already shows those properties inside each variant, because the variants allOf back to the base. The base object block is no longer rendered alongside the selector, so properties like the discriminator field are shown once instead of twice.
#10146: Render a body-level discriminator oneOf flush under its selector. When a oneOf/anyOf variant allOfs back to a shared base — the shape a discriminator.mapping infers, and the one a request body most often carries — the merged variant renders one level deeper than a plain object variant and picked up an extra row of padding, so its first field sat detached below the selector instead of flush under it like a plain oneOf.
#9886: Fix empty $dynamicRef array items in the Models section. A model that binds a
generic template's item type through a $ref sibling $defs (a named
Paginated<User>) lost that binding while resolving the schema for display, so
the item rendered empty. The model now keeps the binding and shows the bound type.
#10096: Only show the "one of" hint above required OAuth scopes when there is more than one alternative scope group to choose between. A single group of required scopes is now listed plainly, even when a scope-free alternative (like an API key) also satisfies auth, since those scopes are required together rather than being a choice.
#9677: fix: render the variant selector for discriminator-only schemas used as array items without infinite recursion
A polymorphic base that declares only a discriminator.mapping (no explicit oneOf) and whose subtypes inherit through allOf: [$ref base, …] now renders its "One of" variant selector consistently, whether the base is used directly as an object property or as array items. Previously the merged subtype re-surfaced the base's discriminator, which made it look like the base again and drove the selector inference into infinite recursion.
#10197: Preserve host-app hash prefixes when copying section links or navigating in embedded API references. Detect the prefix from the loaded navigation once and use it consistently when writing links, reopening them, and restoring browser history. Explicit pathRouting.basePath configuration takes precedence and is recommended when host routes overlap with Scalar section IDs.
#10154: Fix recursive variant selectors for schemas whose oneOf or anyOf variants inherit their base through allOf. Keep inherited fields and independent choices without showing sibling variant fields or overflowing the stack when all schema properties are expanded.
#10159: Add test coverage for nested schema selector titles and selections.
#9851: Preserve mutualTLS security schemes and the default request body view extension in OpenAPI 3.2 document schemas and types.
Render OpenAPI 3.2 querystring parameters in the query parameters section.
#10131: Copy the example shown in the response card, including named, generated, referenced, and falsy values.
#10074: perf(api-reference): make the schema renderer cheaper to mount and expand
A profiling pass over the schema renderer, measured against a controlled mount benchmark and a real browser on a large OpenAPI document. Rendered output is unchanged: the previous schema layout is byte-identical across 332 comparisons on 78 real operations, and the tree layout differs only by a scoped-style attribute that no rule selects.
The tree's hover affordances no longer anchor on :has(:hover). Those selectors made every row inserted into an open tree invalidate style across the surrounding subtree, so expanding one schema restyled 9,592 elements. The same states are now written as data attributes from pointerenter and pointerleave, derived from the same DOM adjacency, which takes that to 142 elements and cuts style recalculation on a pointer sweep across an open tree by roughly 85%.
Rows also do less work: the type signature renders inline instead of through a child component, SpecificationExtension and WithBreadcrumb are no longer mounted on rows where they render nothing, property names are sorted from a single read per name and memoised per properties object, a collapsed row counts its children from the key list, and an open row no longer sorts twice. The localization fallback resolves lazily rather than allocating per component instance.
Two changes affect the public Schema and SchemaProperty exports:
Schema root. Documents are added and replaced whole, so this is invisible in normal use, but a consumer that mutates a schema object in place will no longer trigger a re-render. Lazy $ref bundling through the store's resolve API is incompatible for the same reason.sortPropertyNames returns a frozen, shared array. A consumer that sorted the result in place will now throw instead of silently reordering a list other readers depend on.#10074: fix(api-reference): accessibility pass over the schema tree and parameter rows
Restores list semantics on the four lists the theme reset strips, which Safari and VoiceOver otherwise drop entirely. Gives the parameter row trigger a real focus indicator instead of drawing one on its 12px caret. Makes the Default and Examples popovers dismissible with Escape and openable by click or tap, with aria-expanded on their triggers — previously they revealed on hover and focus through CSS alone, so Enter did nothing and touch could not reach them at all. Names the copy buttons that previously announced as their bare value, adding common.copyDefault and common.copyExample across all eight locales. Gives the single content type readout a role, and honours prefers-reduced-motion.
The collapsible section trigger no longer nests the copy-link button inside the toggle button. Nested buttons are invalid, and the parser hoisted the inner one out, so the copy-link sat outside the control it appeared to belong to. The toggle moved inside the anchor instead, where it has to stay inline so the copy-link keeps aligning to the last line of a wrapped heading; it stretches its own hit area back across the full row, so the click target is the whole section row exactly as before.
ScreenReader moves off the deprecated clip property to clip-path and adds white-space: nowrap, so multi-word announcements are no longer split at wrapped word boundaries. Its visually-hidden style is now a shared .screenreader-only class rather than a scoped one, so other components can hide text without wrapping it in the component.
No visual change: every fix above is either invisible, or applies only to focus, hover, or an explicit reduced-motion preference.
#10136: Restore modal and single-file reference tests, update layout selectors, and remove stale comments. Named-resource resolution remains unsupported and is tested explicitly.
#10194: Fix editing server variables supplied through the configuration.
#10140: Replace redundant type assertions with compiler-checked annotations, typed accumulators, and existing guards across helpers, API conversion, request handling, and schema rendering.
Narrow DOM elements and caught errors before accessing their properties. Correct header lookup to include missing values and handle them during PowerShell snippet generation.
Validate release-note provider responses, represent unresolved references and absent groups in helper return types, and require narrowing merged object values. Preserve AsyncAPI broker credentials separately from HTTP authentication schemes.
#10168: Render AsyncAPI message traits, including inherited headers, while preserving message-level overrides.
### Minor Changes - #9937: Add a way to open the request body editor in the Form view by default. Set the defaultRequestBodyView: 'form' config option
defaultRequestBodyView: 'form' config option, or the x-scalar-default-request-body-view extension in your OpenAPI document (which also works per source). Defaults to raw, and falls back to raw when a body cannot be shown as a form.A block now assumes it is the top of the page: rendered alone, an operation's title is the h1 and everything it contains follows beneath it. A compone
#10043: Resolve heading levels from a block's place in the page outline instead of hardcoding them, so a block rendered on its own starts at h1.
A block now assumes it is the top of the page: rendered alone, an operation's title is the h1 and everything it contains follows beneath it. A component that renders several blocks alongside each other owns the relationship between them and anchors the outline — Content renders the info block above the tags and operations, so it declares document and the rest resolve against it. Composed into a full reference, every heading renders at the level it always has.
Also fixes two headings that never went through the heading components: the classic-layout operation title was a raw h3, and the classic-layout Models section label passed a level prop to a component that does not accept one, so it rendered no heading element at all.
feat: test OpenAPI webhooks from the API reference and API client
zod catalog to ^4.4.3 so the standalone bundle ships a single zod instead of two (4.3.5 from @scalar/types plus 4.4.3 from the ai / @ai-sdk peer). This makes standalone.js ~68KB raw / ~18KB gzip smaller.$ref allOf (a common inheritance pattern), flattening that allOf for display left the base schema's own identity ($ref, title, or name) on the flattened variant, so the selector picked up the base's name for every branch instead of each branch's own name.http and apiKey schemes. Scopes are only meaningful for oauth2 and openIdConnect schemes, so the section is now skipped when the resolved scheme is of a different type.Pattern hover chip next to the Example chip so it no longer collides with the preceding constraint (for example max length: 26Pattern). Real constraints like length and nullable now stay together in the dotted list.### Patch Changes - #9941: Republish every package through npm trusted publishing. No functional changes.
Nothing published for this version
### Minor Changes - #9884: Export the AsyncAPI content components (AsyncApiChannel, AsyncApiOperation, AsyncApiMessage, AsyncApiTraversedEntry) from @
@scalar/api-reference/components so downstream renderers can render an individual channel/operation/message on its own page.hideModels, or when the referenced model itself was hidden via x-internal / x-scalar-ignore. There was nothing to scroll to, so clicking them did nothing. They now render as plain text in both cases.$ref actually targets #/components/schemas/. Refs into other component buckets (parameters, responses, ...) or external files now show the name as plain text instead of a dead link that scrolls nowhere.x-tags. The models index now collects model entries from the whole navigation tree, so clicking a model name that lives under a tag group scrolls to the model instead of doing nothing.Sidebar items used aria-selected on links/buttons (invalid for those roles) and the search trigger used role="search" on a button. Selected items now
#9828: Bump shared build and runtime dependencies to their latest compatible versions
(fuse.js, vite, vitest, tailwindcss, @vitejs/plugin-vue, @vue/test-utils,
posthog-js, yaml, and the CSS injection plugin). The fuse.js 7.5.0 upgrade
tightened generic inference, so the empty new Fuse([]) search instances now
pass an explicit FuseData type argument.
#9837: Keep the selected server when the configuration is updated. Pushing a config update to a mounted reference (for example a refreshed auth token via updateConfiguration) rebases the document in the store, which previously reset the server selector back to the first server. The user's selected server is now preserved across configuration updates.
#9783: fix: resolve axe-core ARIA violations in the API reference sidebar and client tabs
Sidebar items used aria-selected on links/buttons (invalid for those roles) and the search trigger used role="search" on a button. Selected items now use aria-current="page", the search control is a plain named button, and the sidebar no longer sets an invalid role="navigation" on <aside> (it keeps the default complementary landmark).
Client library and SDK installation "More" comboboxes sat inside role="tablist", which fails aria-required-children. They now sit beside the tablist. MCP install controls without a target URL render as buttons instead of empty a[href=""] links.
#9791: Stop recursive schema rendering when a discriminator variant allOfs back to its base type. The selected child now inherits the parent's discriminator context so the mapping is not re-inferred on every nest.
#9830: Stop listing enum values twice for an array parameter whose items is a $ref
to an enum schema. The values are now listed only in the array items card, which
also shows the item schema's title and description.
#9839: Harden the API reference against untrusted OpenAPI documents:
info.license.url, info.termsOfService,
info.contact.url, externalDocs.url, x-scalar-links) and the direct download link are now
checked against an allow list of protocols, so a document can no longer render a javascript:
link that runs script when a reader clicks it. Unsafe values fall back to plain text.deepMerge (used by the exported createEmptySpecification) no longer writes through the
prototype chain, so a document can no longer add properties to Object.prototype via __proto__,
constructor, or prototype. Keys with those names are kept as plain data instead of being
dropped, so a schema is still free to describe a property named constructor.customCss can no longer close the injected <style> tag, which mattered during server
rendering where the value lands in the HTML stream verbatim.rel="noopener noreferrer" to the remaining target="_blank" links.Adds isSafeUrl and sanitizeUrl to @scalar/helpers/url/is-safe-url.
#9829: Update Vue to 3.5.40. Vue 3.5.36 tightened defineModel default validation, so
models with array or object defaults now use the factory form
(defineModel<T[]>({ default: () => [] })) as Vue already requires for regular
props. Behaviour is unchanged.
#9790: fix: keep dots in webhook navigation deep links
Webhook event names that use dots (for example account_holder.created) had the
dot dropped when building the navigation id, joining adjacent words into
account-holdercreated. Dots are now kept, producing account-holder.created.
Old deep links using the dropped-dot slug are redirected to the new slug, so existing bookmarks keep resolving.
Each entry must point to an ESM module that exports a plugin (the same shape as the plugins entries) as its default export. The standalone build (Scal
#9683: Surface the required OAuth scopes for an operation as a dedicated "OAuth scopes" section below the description (above parameters), instead of only inside the "Auth Required" badge popover. Scopes are de-duplicated across security alternatives and shown in both the modern and classic layouts, as well as on AsyncAPI operations.
#9711: feat: add pluginUrls configuration option to load API Reference plugins from URLs
Each entry must point to an ESM module that exports a plugin (the same shape as the plugins entries) as its default export. The standalone build (Scalar.createApiReference) imports the modules before the API reference mounts and registers their default exports alongside the plugins passed directly. Unlike plugins, the new option is JSON-serializable, so integrations that pass their configuration as JSON (for example the Docker container or Scalar for Aspire) can load plugins without replacing the whole bundle.
#9732: Render every oneOf/anyOf group of an allOf in place. Previously, when one object composed several mutually-exclusive choices as sibling oneOf/anyOf under allOf, only the first group was shown and the rest were silently dropped. Each choice group now renders its own selector in the position it was declared, and the generated request example stays in sync per group.
#9794: Keep sibling properties when flattening a single-member allOf. Previously, a schema declaring its own properties next to an allOf holding a single $ref lost those sibling properties: the referenced schema's properties overwrote them instead of being combined, and the referenced schema's title/description replaced the parent's. Sibling and inherited properties now render together, required lists are unioned, and the parent schema's own annotations win over the base it extends.
#9757: fix: read enum metadata from array items
When an enum is defined inside an array schema's items, the enum values were resolved from items but their x-enum-varnames, x-enumNames, and x-enumDescriptions were still read from the outer schema, so the metadata was dropped. Both the values and their metadata are now read from the same schema.
#9681: The "Auth Required" / "Auth Optional" badge on operations now opens on hover, not just on click
#9753: fix: badge base styles no longer rely on zero specificity
The badge base rule was written with :where(.badge), which the scoped-style compiler collapsed to zero specificity, letting any late-loading reset clobber the badge font size, padding, and colors. The base styles now carry real specificity, and consumers that intentionally override them (the download-link json/yaml badges and the webhook badge) keep winning through tailwind-merge and higher-specificity variant rules.
#9766: fix: give the collapsible section trigger an accessible name and a valid aria-controls target
The trigger button rendered by CompactSection carried aria-controls set to its own id, so it declared that it controls itself, and it exposed no accessible name of its own. Screen reader users heard an unnamed button, and axe-core reported button-name and aria-allowed-attr on every model section.
The trigger now points aria-controls at the collapsible region, which carries its own id. While the section is collapsed the attribute is dropped entirely rather than left pointing at an element that is not rendered.
The accessible name now comes from aria-labelledby pointing at the heading the trigger already renders, so the name is always the visible text. Referencing the heading rather than copying it into an aria-label means the name cannot drift out of sync with what is on screen, which is the WCAG 2.5.3 (Label in Name) failure a duplicated string would risk.
#9754: fix: adapt the info links to the rendered width of the reference instead of the viewport
The introduction's info links (contact, license, terms of service, external docs, and x-scalar-links), the section header grid, and the classic-layout selector cards switched their layout based on viewport media queries, while the rest of the reference adapts to the rendered width of the reference through the narrow-references-container container query. They now restyle based on the container as well, through a new narrow: Tailwind variant.
#9751: fix: keep even heading-to-description spacing on the operation title in narrow layouts
The narrow (single-column) operation layout bumped the operation title's bottom margin to 24px, so the gap between the heading and its description no longer matched the 12px used on wider screens. The override is removed so the title keeps the shared 12px spacing at every width.
#9676: Preload additional documents in a multi-document setup while the browser is idle, so switching between them is instant.
#9788: Add print styles so printing (or saving to PDF) no longer renders expanded content over the text that follows it. The reference lays itself out as a fixed-viewport application, and its sticky columns were pinned to a screen measurement that is meaningless on paper. Printing now flattens that shell into ordinary document flow: navigation and floating chrome are hidden, sticky positioning and viewport-derived height caps are dropped so long examples are no longer truncated, and small units such as properties and cards avoid breaking across pages.
#9691: Show the format of primitive array items (e.g. an array of uuid strings) in the schema property heading
### Minor Changes - #9728: feat: export SdkInstallationInstructions and getRenderableSdks from @scalar/api-reference/blocks, so consumers that compose
SdkInstallationInstructions and getRenderableSdks from @scalar/api-reference/blocks, so consumers that compose their own reference layout can render x-scalar-sdk-installation again### Patch Changes - #9719: docs: update the Scalar platform overview block in the README
The radius tokens used to be independent, so setting --scalar-radius: 0 still left rounded corners behind on anything using --scalar-radius-lg, --scal
#9687: feat(themes): derive the border radius scale from --scalar-radius
The radius tokens used to be independent, so setting --scalar-radius: 0 still left rounded corners
behind on anything using --scalar-radius-lg, --scalar-radius-xl or rounded-full. They now all
derive from --scalar-radius, which means overriding that single variable rescales every corner in the
interface, and 0 squares it off completely.
Two new tokens fill out the scale, --scalar-radius-2xl (12px) and --scalar-radius-3xl (16px), along
with --scalar-radius-full for pills and circles. The matching rounded-2xl and rounded-3xl Tailwind
utilities now emit CSS; previously they were silently dropped.
Every default value is unchanged, so nothing shifts unless you were relying on the old behaviour. If
your theme sets --scalar-radius on its own and expects the larger radii to stay put, set those tokens
explicitly. Override --scalar-radius on :root: a custom property substitutes var() at the element
where it is declared, so setting the base further down the tree moves it without moving anything derived
from it.
Nothing published for this version
### Patch Changes - #9618: Render document-wide authentication for AsyncAPI documents. The introduction now shows the same Authentication selector use
components.securitySchemes, with requirements derived from the union of every server's security (AsyncAPI has no root-level security). When some servers require auth and others accept unauthenticated connections, a no-auth option is offered too. Schemes shared with OpenAPI (http, oauth2, openIdConnect, apiKey) get full input UI, and AsyncAPI OAuth2 availableScopes are mapped onto OpenAPI scopes so the scope list renders. Broker-specific types still appear in the selector but have no dedicated input yet. The selector is now fully interactive for AsyncAPI (selecting schemes, entering credentials, editing scopes) because the auth mutators accept AsyncAPI documents. Operation/channel-level auth is intentionally left for a follow-up.documentType prop on the auth selector block, defaulting to openapi. Schemes that carry a valid but unsupported type (such as AsyncAPI broker types like userPassword or scramSha256) now show a dedicated "not supported yet" message naming the type, instead of the misleading "missing a type" warning.auth accessor reading from the wrong store. It now reads from the client store — the same store the reference-side Authentication panel writes credentials into — so plugins see the secrets and selected security schemes the user actually entered instead of an empty state.When a schema used allOf to factor out shared object properties next to a oneOf/anyOf, each branch's own properties/required overwrote the shared base
#9671: Add a canDeleteSchemes prop to the auth selector so the delete (trash) affordance can be hidden. It defaults to true (unchanged for the API client, where schemes are editable) and the API reference now passes false, since its schemes come from the rendered document and cannot be removed there.
#9646: Fix deep links to response properties. Response property anchors now carry a responses marker so the target operation is found and scrolled to on a fresh load, and response properties are linkable even when expandAllResponses is off (a deep link expands the collapsed response and scrolls the property into view).
#9631: Hide the protocol and server filters in the classic layout for AsyncAPI documents
#9639: Add a read-only accessor for the global authentication state to the plugin API. Plugin lifecycle hooks (onInit, onConfigChange) now receive an auth accessor alongside config, and the plugin manager exposes getAuthState() for view components. Plugins can read stored secrets and the selected security schemes via auth.export(), auth.getAuthSecrets(documentName, schemeName), and auth.getAuthSelectedSchemas(payload) without being able to mutate auth.
#9664: fix: keep base allOf properties when merging oneOf/anyOf branches
When a schema used allOf to factor out shared object properties next to a oneOf/anyOf, each branch's own properties/required overwrote the shared base fields instead of being combined with them. The base fields now stay visible alongside each branch's own fields.
Nothing published for this version
Nothing published for this version
### Patch Changes - #9630: Render AsyncAPI tags without the extra horizontal indentation on nested channels, and replace the empty "Operations" card i
### Patch Changes - #9575: Render the discriminator variant dropdown for object schemas that only declare a discriminator.mapping (no explicit oneOf/a
discriminator.mapping (no explicit oneOf/anyOf), which is the shape NSwag emits for polymorphic types$dynamicRef in schemas, so generic patterns like PaginatedResponse<T> show their concrete bound item type (for example User[]) instead of an empty shape. The reference threads the active dynamic scope through the schema tree and binds each $dynamicRef to the matching $dynamicAnchor.Maximum call stack size exceeded crash when rendering a schema whose self-reference is reached through an allOf branchUpdate the shared theme reset so text inputs align to the logical start by default for RTL documents.
#9597: Add API Reference UI localization configuration with built-in English, Russian, Spanish, French, German, Simplified Chinese and Arabic translations, including automatic RTL direction for Arabic locales.
Update the shared theme reset so text inputs align to the logical start by default for RTL documents.
Add a mergeObjects deep-merge helper to @scalar/helpers, used by the localization layer to merge translation overrides onto the built-in locale.
#9568: Add AsyncAPI protocol and server pickers to the sidebar (like the multi-document picker) that filter the navigation down to the operations reachable over the selected protocol/server
#9543: Add the x-scalar-links OpenAPI extension to render extra named links (like a privacy policy or imprint) next to the contact, license and terms of service links in the introduction.
#9545: Render the divider between the contact email and url links in the introduction, so they are separated like the other info links.
#8519: refactor: extract the code example block into @scalar/blocks/code-example. api-client, api-client-react, and api-reference now import CodeExample, findClient, generateClientOptions, and the related helpers from the new package. workspace-store exports isParamDisabled with an optional defaultDisabled argument.
Breaking (@scalar/api-client): the @scalar/api-client/blocks/operation-code-sample and @scalar/api-client/v2/blocks/operation-code-sample export paths have been removed. Import from @scalar/blocks/code-example instead, and use the renamed CodeExample / CodeExampleProps (previously OperationCodeSample / OperationCodeSampleProps).
#9578: Show the propertyNames type and format (e.g. string · uuid) for a map of additional properties, so key constraints are no longer dropped from the rendered schema
#9548: Keep request and response example pickers in sync across operations. Selecting an example (e.g. "Use case 1") now selects the example with the same key on every other operation that defines it, mirroring how the programming-language selection already syncs. Operations that do not have a matching example keep their current selection.
The hook runs after the request has been built, right before it is sent. Header mutations apply to the outgoing request and the body bytes match what
#9520: Render AsyncAPI operations and their messages (with payload and header schemas) nested inside each channel, in both the modern and classic layouts
#9569: Show server and protocol labels when rendering AsyncAPI channels and messages: each channel header lists the servers it's available on and their protocols, and each message surfaces every protocol it's carried over (its channel's server protocols unioned with its own binding protocols)
#9515: feat: add requestBuilt client plugin hook and onRequestBuilt configuration callback that receive the exact fetch Request that is sent over the wire
The hook runs after the request has been built, right before it is sent. Header mutations apply to the outgoing request and the body bytes match what the server receives, which makes request signing possible: hashing the body of a rebuilt multipart/form-data request would produce a different multipart boundary than the request that is actually sent.
anyOf/oneOf/allOf/not)<style> tag: the CSS is now rendered verbatim instead of being HTML-escaped on the server (" became "), which broke font styles and caused a hydration mismatch.allOf member override the description and title of an earlier oneoneOf/anyOf being dropped when nested inside an allOf. The composition is now preserved so its variants keep rendering alongside the merged base properties, instead of only the first allOf member showing up.`content.start`: A new view slot that renders custom plugin components before the Introduction/Info section (at the top of the content area).
content.start plugin view slot and sidebar visibility option for plugin view components.
content.start: A new view slot that renders custom plugin components before the Introduction/Info section (at the top of the content area).sidebar option on ViewComponent: Plugins can now opt-in to display a sidebar entry for their custom views by providing sidebar: { show: true, label: 'My Page' }. Omitting sidebar or setting show: false hides the entry from the sidebar. The entry hooks into the existing navigation, so clicking it scrolls to the plugin view and it highlights as it scrolls into view.allOf, oneOf, or anyOf)expandAllSchemaProperties.expandAllResponses is enabled. A response's own description and its content schema's description are now both shown.max-width: 1000px while the sidebar visibility is driven by Tailwind's lg: variant (min-width: 1000px), so both fired at 1000px. The mobile breakpoint now uses width < 1000px, the exact complement of lg:, so 1000px is treated as desktop.Path entries and webhooks can reference components.pathItems instead of inlining operations. Navigation, mutators, search, and markdown export now res
#9396: Refactor URL redirects into a routing-agnostic, list-driven engine. Redirects now operate on the bare navigation id, so each rule works across hash, hash-base-path, and path routing automatically. Also redirect old models/<name> bookmarks to the configured models section slug when the section label is customized (e.g. schemas/).
#9489: Do not render the info link list when no links are available.
#9342: fix: resolve operations when OpenAPI path items use $ref
Path entries and webhooks can reference components.pathItems instead of inlining operations. Navigation, mutators, search, and markdown export now resolve path-item references before reading HTTP methods and path-level parameters.
#9498: Sync the SDK installation tabs with the operation code examples: picking a language under "Client Libraries" now switches every operation's code sample to that language's custom example
### Patch Changes - #9471: Restore support for the deprecated source install command on x-scalar-sdk-installation. When set, it is appended to descrip
source install command on x-scalar-sdk-installation. When set, it is appended to description as a fenced code block (or used on its own when there is no description). description remains the promoted field.### Patch Changes - #9462: fix(api-reference): align examples panel and disable sticky when narrow
Channel address parameters (the {param} placeholders in a channel address) are now shown in the API reference, reusing the same parameter list compone
#9435: feat(api-reference): render AsyncAPI channel parameters
Channel address parameters (the {param} placeholders in a channel address) are now shown in the API reference, reusing the same parameter list component as OpenAPI operations. Their enum, default, and examples are displayed on a string schema.
#9438: feat(api-reference): add an AsyncAPI server selector
Adds a server selector for AsyncAPI documents in the API reference introduction. It mirrors the OpenAPI server selector but works with the AsyncAPI server shape (a named map of host/protocol/pathname), labelling each server with its constructed connection URL.
Server selection and variable changes are now persisted to the workspace store via new asyncapi-server:update:selected and asyncapi-server:update:variables events and their mutators, mirroring the OpenAPI wiring.
#9422: Add a nonce option for Content Security Policy support.
When you pass a nonce, the rendered HTML stamps it onto the inline <script> and the CDN <script> tag (and Scalar's own <style> tags, plus a matching <meta property="csp-nonce">). This lets the API Reference run under a strict script-src with no unsafe-inline and no unsafe-eval.
ApiReference({
url: '/openapi.json',
// Match this value in your `script-src` CSP directive.
nonce: 'r4nd0m',
})
Note: style-src still needs 'unsafe-inline'. The reference renders inline style="…" attributes, which a CSP nonce can never authorize (nonces only apply to <script>, <style> and <link> elements), so a nonce-only style-src is not possible. The win is a fully strict script-src.
#9400: feat(api-reference): add expandAllSchemaProperties config option.
When enabled, nested schema properties are expanded by default while keeping the "Show/Hide Child Attributes" button available for manual collapsing. Expansion is cycle-safe: every finite branch is expanded fully, and self-referential ($ref or inline) schemas stop at the point they would otherwise recurse forever.
#9399: Show custom SDK installation instructions from x-scalar-sdk-installation in the introduction card, falling back to the client selector when there are none. Each entry takes a lang and a Markdown description, so a single tab can render rich instructions with syntax-highlighted code blocks (for example Maven and Gradle for Java)
#9388: Add ScalarVirtualCodeBlock component with copy button support for virtualized code blocks
#9436: Hide the client selector for AsyncAPI documents
#9398: feat: read code samples from x-readme, x-stainless and x-scalar extensions
In addition to x-codeSamples, the code sample picker now reads custom samples from x-scalar-examples, x-stainless-snippets, x-stainless-examples, and x-readme.code-samples. When more than one is present on an operation, the highest-priority source is used (x-scalar-examples > x-stainless-snippets > x-stainless-examples > x-readme > x-codeSamples).
#9426: feat(api-reference): render the contact URL from info.contact.url
#8573: fix(api-reference): infer discriminator variants from mapping
#9131: fix(api-reference): preserve OAuth redirect URI when switching OpenAPI documents
When using multiple OpenAPI documents with OAuth configured via oauth2RedirectUri,
switching to another document no longer clears the Redirect URL in the Authentication
section.
The fix threads oauth2RedirectUri from the top-level configuration into the security
scheme merge chain so that each newly loaded document's OAuth flows are pre-populated
with the configured redirect URI, rather than relying solely on a component-level watcher
that would skip re-population when the same OAuth flow identity was detected across
documents.
#9391: fix: stabilize the tab title at the top of the document
The document-start sentinel and the Introduction section both fire an intersection event at scroll-top. They resolved to different entries, so the tab title raced between the section title and the document title. The sentinel now emits the Introduction entry, so both agree.
#9370: fix(api-reference): rework the modern operation layout with CSS grid so the request example sits directly under the description on narrow screens, and move the operation title and auth badge into the same grid
#9421: fix(api-reference): avoid SSR hydration mismatch from the search shortcut and teleport ids
The macOS search shortcut symbol was derived from navigator during render, so a Mac client hydrated ⌘ where the server sent ⌃. The platform is now resolved after mount. Teleport target ids and the search modal ids also switched from nanoid() to Vue's SSR-stable useId().
#9392: Clean up the standalone build's injected <head> styles on destroy() so they no longer linger after SPA-style navigation (Turbo Drive, htmx). The styles are re-attached when a new instance mounts.
#9420: fix(api-reference): make x-tagGroups titles navigable from search
Tag group titles appeared as search results but clicking them did nothing, because the flattened modern layout rendered no element carrying the tag group id to scroll to. The group now exposes its id as a scroll anchor.
Pass a setPageTitle function to control the browser tab title. It is called whenever the section in view changes — on sidebar clicks, on scroll, and w
#9372: Render AsyncAPI components.schemas as Models, listed in the sidebar and content just like OpenAPI schemas
#7618: feat(api-reference): add setPageTitle to customize the browser tab title
Pass a setPageTitle function to control the browser tab title. It is called whenever the section in view changes — on sidebar clicks, on scroll, and when switching documents — and receives the section title and the active OpenAPI document:
setPageTitle: ({ title, document }) => `${document.title} – ${title}`
#9348: Render AsyncAPI channels as sections in the content area, with the channel address as the heading and the channel description below. Channels are grouped under tags when the navigation tree groups them. Operations and messages are not rendered yet.
#9255: Surface the Introduction entry and any headings extracted from info.description of AsyncAPI documents in the sidebar, mirroring how OpenAPI documents are handled.
#9347: Surface AsyncAPI info.description headings in the search modal, mirroring the sidebar behaviour. AsyncAPI channels, operations, and messages are not indexed yet.
#9350: feat(api-reference): list Ask AI and MCP Servers as Scalar Docs features in the Deploy popover
#9310: Add an ESM standalone build (dist/browser/standalone.esm.js) alongside the existing UMD bundle. The new bundle works as a side-effect script (registers window.Scalar.createApiReference and reads data-* configuration) and exports createApiReference for direct ESM consumers. It is fully minified through Rolldown's native minifier and uses code splitting so heavy features load asynchronously after first paint:
await import'd inside onMounted instead of statically imported, moving ~265 KB into a chunks/modal-*.js chunk that loads in the background.defineAsyncComponent) becomes a real chunks/AgentScalarChatInterface-*.js chunk (~200 KB), loaded only when the agent is enabled.@scalar/icons/library are coalesced into a single chunks/icons-*.js.Net effect: initial sync load drops from ~3.32 MB (UMD) to ~2.73 MB (ESM) — a ~570 KB improvement — while total bundle size shrinks by ~140 KB.
Also adds an @scalar/api-client/modal/map-hidden-clients-config deep export so consumers that only need the lightweight client-list helper don't pull the full modal barrel into their static graph.
#9139: fix(api-reference): preserve OAuth redirect URL when switching between OpenAPI documents
Auth changes were being persisted under the wrong document slug and shared a single debounce queue across all documents. When switching documents quickly, the pending save for the first document could be overwritten or dropped by a save for the second document, causing the redirect URL (and other auth secrets) to appear cleared after switching back.
The fix uses event.documentName as both the debounce key and the storage key, giving each document its own independent debounce queue.
#9194: fix(api-reference): break cycles in mergeAllOfSchemas for self-referencing schemas (whether they $ref back to themselves through array items or through a plain object property), which previously crashed the docs preview with "too much recursion"
#9309: feat: add modelsSectionLabel configuration ('Models' | 'Schemas' | string) to use OpenAPI-style Schemas terminology in the sidebar, content, and search.
Move the content type picker after the disclosure panel so it stacks above expanded response content and remains clickable when expandAllResponses is
#9318: fix: restore response content type selector when expandAllResponses is enabled
Move the content type picker after the disclosure panel so it stacks above expanded response content and remains clickable when expandAllResponses is true.
Nothing published for this version
### Patch Changes - #9169: feat: add customFetch to the api-reference configuration and forward it to the API client so requests (including "Test Requ
customFetch to the api-reference configuration and forward it to the API client so requests (including "Test Request" calls) use the custom fetch — enabling things like credentials: 'include'. The previous fetch option is deprecated and migrated automatically with a console warning.null, whitespace-only, and value/externalValue-shaped schema examples correctly### Patch Changes - #9234: fix(api-reference): prevent security badge from shrinking
Nothing published for this version
createApiReference() registered three document-level listeners (scalar:reload-references, scalar:destroy-references, scalar:update-references-config)
WorkspaceDocument an union of OpenApiDocument and AsyncApiDocument#9211: fix(api-reference): clean up deprecated document listeners on destroy
createApiReference() registered three document-level listeners
(scalar:reload-references, scalar:destroy-references,
scalar:update-references-config) but destroy() only unmounted the
Vue app — the listeners stayed attached forever. In environments that
mount and destroy instances repeatedly (notably the Astro integration's
renderMode="client" with view transitions), each navigation leaked
three permanent listeners on document.
Tie the listeners to an AbortController and abort it from destroy()
so they all come off in one shot.
#9211: fix: show "Download AsyncAPI Document" label for AsyncAPI documents
#9211: fix: rename the "OAS" version badge to "OpenAPI" and show an "AsyncAPI" badge for AsyncAPI documents
#9211: fix(api-client): block invalid request URLs before send and surface buildRequest failures as results
Request construction now treats a bad merged URL as a first-class failure instead of throwing deep inside helpers. After mergeUrls, resolveRequestFactoryUrl rejects incomplete targets when strict mode applies: relative URLs, an empty server base, or path strings that still contain unresolved {{variable}} placeholders. Callers may set allowMissingRequestServerBase where a full absolute URL is intentionally optional (for example the embedded modal layout in OperationBlock, or API Reference onBeforeRequest hooks that build against the document origin).
buildRequest returns a Result (ok / err) with stable error codes such as MISSING_REQUEST_SERVER_BASE, INVALID_REQUEST_FACTORY_URL, and BUILD_REQUEST_FAILED for unexpected synchronous failures. Those failures are wrapped with safeRun from @scalar/helpers, which logs to console.error and maps throws to a string message on the result. The API Reference plugin path logs and skips onBeforeRequest when a preview request cannot be built, so user hooks never run against a half-built fetch payload.
Downstream packages (api-client, api-reference, scalar-app where applicable) unwrap the result, show toasts or logs, and avoid calling sendRequest until the URL is valid.
#9211: fix(api-reference): improve search ranking for parameter, request-body, and model field names, including polymorphic (oneOf/anyOf/allOf) schemas
#9211: fix: resolve $ref in additionalProperties before rendering schema
#9211: chore: use the new schemas
#9211: Fix mobile sidebar z-index to ensure it appears above all content when open
#9211: Avoid repeating request body schema descriptions above collapsed overflow properties.
#9211: feat: add more analytics events
#9211: fix: agent scalar warnings
#9211: fix(api-reference): lower badge style specificity
#9211: fix: posthog stream warning
### Patch Changes - #9095: fix(api-reference): use overflow-wrap break-word for tag labels
### Patch Changes - #9076: fix(api-reference): improve rendering of virtualized code blocks - #9086: feat: code split tailwind CSS to reduce bundle si
### Patch Changes - #9023: chore: use homemade slugger
### Minor Changes - #9045: feat(api-reference): show an "auth required" / "auth optional" badge next to each operation's path. Requirements are resolv
operation.security ?? document.security; hover reveals the scheme names, types, and any required scopes.### Minor Changes - #8970: feat(api-reference): show an "auth required" / "auth optional" badge next to each operation's path. Requirements are resolv
operation.security ?? document.security; hover reveals the scheme names, types, and any required scopes.Nothing published for this version
### Minor Changes - #8772: feat: link to model from endpoints
Nothing published for this version
Nothing published for this version
### Patch Changes - #8884: fix: restore position: fixed on .section-flare so the decorative hero flare stops reserving 100vh of empty space at the top
position: fixed on .section-flare so the decorative hero flare stops reserving 100vh of empty space at the top of the documentation (affects the kepler, bluePlanet, and mars themes, which declare height: 100vh on the flare but rely on the framework to position it)### Patch Changes - #8810: refactor: move telemetry to an optional plugin - #8911: feat: switch from Request to RequestPayload to support body with GE
### Patch Changes - #8827: chore: removed old client v1 code - #8791: fix test requests so exploded array query parameters keep all values instead of
### Patch Changes - #8769: feat(themes): add Tailwind v3 transform reset - #8767: feat(api-reference): collapse truncated descriptions - #8776: fix: h
### Minor Changes - #8750: feat: display model name for body section - #8695: feat: suport pre/post request scripts ### Patch Changes - #8431: fix: SS
### Minor Changes - #8712: feat: use separate stores for client and shared state on the reference ### Patch Changes - #8728: fix: correctly merge secu
### Minor Changes - #8524: feat: move request logic on the store and generate a request builder - #8609: feat: display tag groups for classic layout #
Your coding agent can read these notes before it upgrades. Set up the MCP server →