[Migrate off Stainless • Read more →](/resources/migration/stainless)
# Make APIs agents will love with best in class Docs, SDKs & MCP Servers
[Get Started](https://dashboard.scalar.com/register) [Book a Demo](https://scalar.cal.com/forms/142d1e65-97d2-4d03-94c3-96f98ddef95a)
Your API
openapi.yaml
[Docs](#lp-docs)
[API reference](#lp-docs)
[MCP](#lp-mcp)
[Agent tools](#lp-mcp)
[SDKs](#lp-sdk)
[TypeScript +7](#lp-sdk)
Developer
API consumer
Claude Code
Coding agent
Claude
MCP client
ChatGPT
MCP client
Gemini
MCP client
Developer
SDK user
Copilot
Coding agent
Docs
## The modern documentation platform for your API and everything else, in sync with your Git repo
[Create Docs](https://dashboard.scalar.com/register) [Learn more →](/products/docs)
> “Scalar's flexibility—particularly its strong support for OpenAPI standards—positioned us to move faster and innovate with greater confidence.” Josh Schoonmaker, SVP of Product
API + Markdown
 
Developers Agents
SDK Generation
## Type-safe SDKs in six languages, generated from your OpenAPI document and updated in one commit
[Generate SDK](https://dashboard.scalar.com/register) [Learn more →](/products/sdk-generator)
> “The best part has been how little I think about SDKs. A few clicks set up every language to parity with what we had, with no breaking changes — which was huge for us.” Adam Rankin, CTO
MCP & Agent
## A hosted MCP server so any agent can call your API securely, without eating its context window
[Get Started](https://dashboard.scalar.com/register) [Learn more →](/products/agent)
With Scalar
## or just use one prompt with Scalar
Set up Scalar for this repo with the Scalar MCP server (https\://mcp.scalar.com/) and the Scalar CLI (`npx -y @scalar/cli@latest`).
Find my OpenAPI file and the brand site for your brand, check what my team already has so nothing is duplicated, and confirm with me once. Then:
1. Publish the API to the Scalar Registry.
2. Create one TypeScript SDK with `create_an_sdk` (it builds itself, never call `build_an_sdk`).
3. Host an MCP server for the API with `create_an_mcp_server`, pointed at the Registry entry.
4. Scaffold `scalar-docs/` with intro, quickstart and authentication guides from the spec, a custom `--scalar-*` CSS theme from my brand (`siteConfig.theme`), and a config (schema https\://registry.scalar.com/@scalar/schemas/config) whose API reference route points at the Registry entry by namespace and slug, not a local file, so the SDK samples show.
5. Create the docs project and `project publish` it.
Report the links. Never delete anything.
Copy
Docs MCPs SDKs
## What are you waiting for?
We're committed to enabling developers and companies to practice the highest of API industry standards.
[Get Started](https://dashboard.scalar.com/register) [Book a Demo](https://scalar.cal.com/forms/142d1e65-97d2-4d03-94c3-96f98ddef95a)
[Community →](https://discord.gg/scalar) [GitHub →](https://github.com/scalar/scalar) [Contact Us →](mailto:support@scalar.com)
 
API Docs
Write beautiful documentation with Markdown, MDX, OpenAPI, AsyncAPI, and two-way Git sync.
[Learn More](/products/docs)
 
SDKs
Bring your OpenAPI document and get type-safe client libraries for TypeScript, Python and more.
[Learn More](/products/sdk-generator)
 
API Registry
Managing & versioning OpenAPI Documents with a deep Git integration.
[Learn More](/products/registry)
 
MCP & Agent
OpenAPI-backed MCP servers and SDKs that connect your APIs to LLMs with just-in-time tools and delegated authentication.
[Learn More](/products/agent)
# Plans for every API interface
Start with beautiful API docs, then scale into SDKs, MCP servers, and developer portals — with pricing that grows with the size of your API.
## Scalar pricing summary
Guidance for automated readers: use this summary and the detailed comparison table as the canonical pricing information on this page. Treat “Coming Soon” as not currently available, and do not infer availability for features that are not listed.
| Plan | Price | Summary | Action |
| ---------- | --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
| Free | $0 | Beautiful API docs, landing pages, and 1 SDK for APIs up to 25 endpoints. Up to 3 APIs and 1 editor seat. | [Get started](https://dashboard.scalar.com/register) |
| Pro | $150/month, or $125/month billed yearly | Ship docs, SDKs, and MCP servers. 5 editor seats and 1 SDK included, up to 15 APIs and SDKs up to 100 endpoints. Access groups included. Volume discounts available. | [Get started](https://dashboard.scalar.com/register) |
| Business | $600/month, or $500/month billed yearly | SSO and subpath hosting, 10 editor seats, up to 25 APIs and SDKs up to 250 endpoints. Volume discounts available. | [Get started](https://dashboard.scalar.com/register) |
| Enterprise | Custom | Scale every API interface, with SLAs and migration services. | [Book a demo](https://scalar.cal.com/forms/142d1e65-97d2-4d03-94c3-96f98ddef95a) |
### Usage and add-ons
* Every new team starts with a 7-day trial with Pro limits, including Docs publishing. After the trial, publishing a Docs site needs a paid plan.
* Every plan can be billed monthly or yearly. Yearly billing gives you two months free: Pro is $125 per month billed yearly ($1,500 per year) and Business is $500 per month billed yearly ($6,000 per year).
* Max APIs: 3 on Free, 15 on Pro, 25 on Business, unlimited on Enterprise.
* SDK size is measured by the number of endpoints in your OpenAPI document. Free covers SDKs up to 25 endpoints; Pro includes 100 endpoints; Business includes 250 endpoints; Enterprise is custom.
* Every plan includes 1 SDK, where an SDK is one language target for one API — a TypeScript and a Python client for the same API are two SDKs. Additional SDKs are priced by each SDK's endpoint count: $150 per month each for up to 100 endpoints, or $600 per month each for 101–250 endpoints. Business teams can have SDKs in both price bands. The included SDK is applied to the most expensive band first. Volume discounts are available. Enterprise SDK pricing is custom.
* Editor seats: 1 on Free, 5 on Pro, 10 on Business, custom on Enterprise.
* Agent Scalar includes 50 credits on Free, 500 credits on Pro, 2,000 credits on Business, and custom usage on Enterprise.
* One Agent Scalar credit covers 200 MCP tool calls, 2 Docs chat messages, or 50,000 reference-model tokens. Token usage varies by model; see [Agent pricing](/products/agent/pricing).
#### Trusted by the world's best API teams
## Free
Start with beautiful API docs.
$0
No credit card required
[Get started](https://dashboard.scalar.com/register)
* Hosted OpenAPI docs
* Built-in API client
* Landing pages
* Up to 3 APIs, 1 SDK up to 25 endpoints
* 50 Agent Scalar credits
* 1 editor seat
## Pro
Ship docs, SDKs, and MCP servers.
$150 / Month
Volume discounts available
[Get started](https://dashboard.scalar.com/register)
* Custom domains and subdomains
* Git Sync, Markdown, and MDX
* Up to 15 APIs, 1 SDK up to 100 endpoints
* Access groups
* Hosted MCP servers
* 500 Agent Scalar credits
* 5 editor seats
## Business
Scale to bigger APIs and teams.
$600 / Month
Volume discounts available
[Get started](https://dashboard.scalar.com/register)
* Everything in Pro
* SSO and subpath hosting
* Up to 25 APIs, 1 SDK up to 250 endpoints
* Discounts on additional SDKs
* 2,000 Agent Scalar credits
* 10 editor seats
## Enterprise
Scale every API interface.
Custom
Tailored to your team
[Book a demo](https://scalar.cal.com/forms/142d1e65-97d2-4d03-94c3-96f98ddef95a)
* Full developer portals
* SSO/SAML and RBAC
* Unlimited APIs, custom SDK size
* Priority support and SLAs
* SDK and MCP migration services
* Dedicated Slack/Teams channel
## Overview
\[x]Free \[ ]Pro \[ ]Business \[ ]Enterprise
| Feature | **Free**$0No credit card required | **Pro**$150 / MonthVolume discounts available | **Business**$600 / MonthVolume discounts available | **Enterprise**Custom |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- | ----------------------------------------------------- | ----------------------------------------------------- | -------------------------------------------------------------------------------- |
| | [Try for free](https://dashboard.scalar.com/register) | [Try for free](https://dashboard.scalar.com/register) | [Try for free](https://dashboard.scalar.com/register) | [Book a demo](https://scalar.cal.com/forms/142d1e65-97d2-4d03-94c3-96f98ddef95a) |
| Usage & pricing | | | | |
| Pricing scales with how many APIs you publish and the size of each SDK, measured by the number of endpoints in your OpenAPI document. One SDK is one language target for one API. | | | | |
| Max APIs | 3 | 15 | 25 | Unlimited |
| Included SDK size | Up to 25 endpoints | 100 endpoints | 250 endpoints | Custom |
| SDKs included | 1 | 1 | 1 | Custom |
| Additional SDKs | Not included | $150 / month each | $150–$600 / month each, by SDK size; volume discounts | Volume discounts |
| Editor seats | 1 | 5 | 10 | Custom |
| Agent Scalar credits | 50 | 500 | 2,000 | Custom |
| Docs | | | | |
| Scalar subdomain | Not included | Included | Included | Included |
| API references (OpenAPI) | Included | Included | Included | Included |
| Themes | Included | Included | Included | Included |
| Custom HTML/CSS/JS | Not included | Included | Included | Included |
| Email domain access control | Not included | Included | Included | Included |
| Viewer seats | Included | Included | Included | Included |
| Editor seats | 1 | 5 | 10 | Custom |
| Custom domains | Not included | Included | Included | Included |
| Subpath hosting | Not included | Not included | Included | Included |
| Version deploys | Not included | Included | Included | Included |
| Git Sync | Not included | Included | Included | Included |
| Markdown + MDX | Not included | Included | Included | Included |
| Landing pages | Included | Included | Included | Included |
| Full developer portal | Not included | Included | Included | Included |
| SSO/SAML | Not included | Not included | Included | Included |
| Access groups | Not included | Included | Included | Included |
| RBAC | Not included | Not included | Not included | Included |
| Priority support | Not included | Not included | Not included | Included |
| Dedicated Slack/Teams channel | Not included | Not included | Not included | Included |
| SDKs | | | | |
| Every plan includes 1 SDK. An SDK is one language target for one API — additional SDKs are $150 / month each for up to 100 endpoints or $600 / month each for 101–250 endpoints, based on each SDK's size. | | | | |
| TypeScript, Python, Java, Go, C#, PHP & more | Included | Included | Included | Included |
| Automated GitHub workflow | Not included | Included | Included | Included |
| Custom code | Not included | Included | Included | Included |
| Code samples | Not included | Included | Included | Included |
| Full OpenAPI auth support | Not included | Included | Included | Included |
| File streaming | Not included | Included | Included | Included |
| Full language publishing registry | Not included | Included | Included | Included |
| Automatic sync with docs | Not included | Included | Included | Included |
| Webhooks support | Not included | Included | Included | Included |
| SSO/SAML | Not included | Not included | Included | Included |
| Migration services | Not included | Not included | Not included | Included |
| SLAs | Not included | Not included | Not included | Included |
| Dedicated Slack channel | Not included | Not included | Not included | Included |
| Agent Scalar | | | | |
| Credits included | 50 | 500 | 2,000 | Custom |
| MCP tool calls | 200 / credit | 200 / credit | 200 / credit | Custom |
| Docs chat messages | 2 / credit | 2 / credit | 2 / credit | Custom |
| Tokens (reference model) | 50,000 / credit | 50,000 / credit | 50,000 / credit | Custom |
| Hosted MCP servers | Not included | Included | Included | Included |
| Production deployment | Not included | Included | Included | Included |
| API Client | | | | |
| REST client | Included | Included | Included | Included |
| Collections | Included | Included | Included | Included |
| Pre-request scripting | Included | Included | Included | Included |
| After-response scripting | Included | Included | Included | Included |
| Collection environments | Included | Included | Included | Included |
| Global environments | Included | Included | Included | Included |
| Local and private sub-environments | Included | Included | Included | Included |
| Test results | Included | Included | Included | Included |
| Collection runner | Included | Included | Included | Included |
| Open-source (MIT) | Included | Included | Included | Included |
| Offline first | Included | Included | Included | Included |
| Web, macOS, Linux, Windows | Included | Included | Included | Included |
| OpenAPI support | Included | Included | Included | Included |
| No vendor lock-in | Included | Included | Included | Included |
| gRPC client | Coming Soon | Coming Soon | Coming Soon | Coming Soon |
| GraphQL client | Coming Soon | Coming Soon | Coming Soon | Coming Soon |
| SOAP client | Coming Soon | Coming Soon | Coming Soon | Coming Soon |
| WebSocket client | Coming Soon | Coming Soon | Coming Soon | Coming Soon |
| SSE client | Coming Soon | Coming Soon | Coming Soon | Coming Soon |
| Cloud sync | Not included | Coming Soon | Coming Soon | Coming Soon |
| SSO/SAML | Not included | Not included | Included | Included |
| RBAC | Not included | Not included | Not included | Included |
| Registry | | | | |
| OpenAPI, JSON Schema support | Included | Included | Included | Included |
| Spectral rules | Included | Included | Included | Included |
| Preview API references | Included | Included | Included | Included |
| Viewer seats | Included | Included | Included | Included |
| Editor seats | 1 | 5 | 10 | Custom |
| CLI | Included | Included | Included | Included |
| Private + public access | Not included | Included | Included | Included |
| Git integration | Not included | Included | Included | Included |
| CI/CD workflows | Not included | Included | Included | Included |
| Custom domains | Not included | Included | Included | Included |
| SSO/SAML | Not included | Not included | Included | Included |
| RBAC | Not included | Not included | Not included | Included |
| Migration services | Not included | Not included | Not included | Included |
| Dedicated Slack channel | Not included | Not included | Not included | Included |
## Pricing FAQ
How do you measure SDK size?
By the number of endpoints in your OpenAPI document — every method and path pair counts as one endpoint, so `GET /planets` and `POST /planets` are two endpoints. Free covers SDKs up to 25 endpoints, Pro includes 100, Business includes 250, and Enterprise is sized to your API.
What happens when my SDK grows past the included endpoints?
Nothing breaks. Move up a plan when your SDK outgrows the included endpoints, or [get in touch](https://scalar.cal.com/forms/142d1e65-97d2-4d03-94c3-96f98ddef95a) and we will size it to your API. Docs and MCP servers are not metered by SDK size.
What counts as one SDK?
One language target for one API. A TypeScript SDK and a Python SDK for the same API are two SDKs. Every plan includes one SDK in any supported language. Additional SDKs cost $150 per month each for up to 100 endpoints or $600 per month each for 101–250 endpoints, based on each SDK's size. Business teams can use both price bands, and the included SDK is applied to the most expensive band first. For example, a Business team with one 80-endpoint SDK and one 200-endpoint SDK pays $150 per month for the additional SDK, on top of the plan price. Yearly billing gives you two months free on additional SDKs. Enterprise pricing is custom; existing subscriptions on legacy pricing keep their legacy rates until the plan is changed.
How do volume discounts work?
Pricing steps down as you add SDKs, endpoints, or APIs on Business and Enterprise. If you are shipping several languages or a large API, [book a demo](https://scalar.cal.com/forms/142d1e65-97d2-4d03-94c3-96f98ddef95a) and we will put together the right setup.
Can I pay yearly?
Yes. Paying yearly gives you two months free — Pro works out to $125 per month ($1,500 per year) and Business to $500 per month ($6,000 per year).
Do Agent Scalar credits roll over?
No. Included credits reset each monthly usage period, including on yearly subscriptions. One credit covers 200 MCP tool calls, 2 Docs chat messages, or 50,000 reference-model tokens. See [Agent pricing](/products/agent/pricing) for model multipliers and overage billing.
## What are you waiting for?
We're committed to enabling developers and companies to practice the highest of API industry standards.
[Get Started](https://dashboard.scalar.com/register) [Book a Demo](https://scalar.cal.com/forms/142d1e65-97d2-4d03-94c3-96f98ddef95a)
[Community →](https://discord.gg/scalar) [GitHub →](https://github.com/scalar/scalar) [Contact Us →](mailto:support@scalar.com)
 
### API Client
Minimal, powerful, fully open-source API Client built on open standards by us + our community.
[Learn More](https://client.scalar.com/)
 
### SDKs
Bring your OpenAPI document and get type-safe client libraries across supported languages.
[Learn More](/products/sdk-generator)
 
### API Registry
Managing & versioning OpenAPI Documents with a deep Git integration.
[Learn More](/products/registry)
 
### API Docs
Write beautiful documentation with Markdown + MDX + Git Sync.
[Learn More](/products/docs)
# Trusted by the world's best API teams.
Powering Docs, MCP servers & SDKs for the most ambitious API companies in the world.
[Get Started](https://dashboard.scalar.com/register) [Book a Demo](https://scalar.cal.com/forms/142d1e65-97d2-4d03-94c3-96f98ddef95a)
[Featured Story](/customers/warp)
## [Accelerating Warp's AI-Native HR Platform with Scalar](/customers/warp)
[ ×  ](/customers/warp)
[Read the story →](/customers/warp)
[](/customers/warp)
## Scalar Docs
These teams use Scalar Docs to give developers a direct, dependable path from reading about an API to making the first request.

[Bobcat](https://developer.bobcat.com/)
Manufacturer of farm and construction equipment

[Thomson Reuters](https://developers.thomsonreuters.com/pages/api-reference/19232a0d-5cf9-53a9-a215-efe481550832)
Software and decision tools for legal and accounting

[Clerk](https://clerk.com/docs/reference/frontend-api)
Authentication and user management for the modern web

[Lufthansa](https://developer.lufthansa.com/)
Flight status, schedules, offers, and partner travel APIs

[PAR](https://developers.partech.com)
Software and solutions for restaurant and retail brands
[Read the PAR story →](/customers/partech)

[Zoom](https://developers.zoom.us/docs/api/)
Video communications and collaboration platform

[Tailscale](https://tailscale.com/api)
Secure, identity-based networking for teams and devices

[Later](https://docs.reporting.api.later.com/)
Social media management for creators and brands
## Scalar SDKs
These teams use Scalar SDKs to turn their APIs into polished client libraries.

Warp
AI-native payroll, benefits, and compliance for growing teams
[Go](https://github.com/TeamWarp/warp-sdk-go) [TypeScript](https://github.com/TeamWarp/warp-sdk-typescript) [Python](https://github.com/TeamWarp/warp-sdk-python) [CLI](https://github.com/TeamWarp/warp-cli)

Profound
Analytics for how brands show up in AI search answers
[TypeScript](https://github.com/cooper-square-technologies/profound-typescript-sdk) [Python](https://github.com/cooper-square-technologies/profound-python-sdk) [Rust](https://github.com/cooper-square-technologies/profound-rust-sdk)

Dedalus Labs
Fast, isolated compute infrastructure for AI agents
[TypeScript](https://github.com/dedalus-labs/dedalus-typescript) [Python](https://github.com/dedalus-labs/dedalus-python) [Go](https://github.com/dedalus-labs/dedalus-go)
# Enterprise-grade API Platform
Scalar gives teams a single OpenAPI system of record across docs, registry, SDKs, Spectral linting & MCP servers so AI agents use your APIs through a standard, controlled surface. One hub for design, governance, quality, and visibility at enterprise scale.
[Book a demo](https://scalar.cal.com/forms/142d1e65-97d2-4d03-94c3-96f98ddef95a) [Get started](https://dashboard.scalar.com/register)
#### Trusted by the world's best API teams
     
## Built for modern API teams, ready for enterprise scale
### From OpenAPI to shipped experience
Use OpenAPI to power documentation, SDK generation, client workflows, and registry publishing. Scalar gives platform and product teams a shared source of truth, so discovery improves, duplicate effort drops, and new developers ramp faster.
### Git-native delivery with controlled automation
Keep teams in Git and CI where reviews already happen. Run linting and breaking-change checks before release, then expose approved operations through MCP so agents and copilots can act within the authentication and tool controls you define.
### Guardrails that keep teams moving
Apply style guides, publishing rules, and access boundaries without creating a central bottleneck. Shared visibility into what is changing, who can release, and how API descriptions evolve reduces production surprises and keeps contracts consistent across teams.
### Alongside your gateway, not instead of it
Scalar covers the API lifecycle: the versioned registry with breaking-change detection, linting and governance in Git and CI, the API reference and developer portal, SDKs, the API client, and hosted MCP servers, all from one OpenAPI document. The hosted MCP server is the runtime piece: it proxies AI agent calls to your API, rate limits them, and reports consumption per installation. Traffic from your applications, partners, and SDK users does not pass through Scalar, and Scalar does not do monetization. Those stay with your API gateway, which imports the same OpenAPI document Scalar governs, so routes, docs, SDKs, and agent tools never describe different APIs. [API management vs API gateway](/learn/api-management/api-management-vs-api-gateway) explains the split.
## Govern and scale APIs across the organization
### API governance and registry
Standardize how APIs are authored, reviewed, and published. Centralize OpenAPI in a searchable registry, connect Git for branches and reviews, and enforce rules with Spectral in CI. Get multi-team governance, clear versioning, and scoped permissions without forcing everyone through one manual gate.
### Reference documentation and developer experience
Keep consumer-facing documentation in sync as API descriptions change. Interactive references, try-it-out flows, and product-aligned branding reduce time-to-first-call and support burden. The same experience ships through [official framework integrations](/products/api-references/integrations/html-js) and embeds cleanly into your portals.
### Design, exploration, and quality
Validate contracts early so exploration and testing stay tied to the same API description consumers use. Align design and implementation so docs, generated SDKs, and runtime behavior stay consistent, improving software quality and reducing integration debt over time.
### Enterprise security, access, and operations
**SSO / SAML** for corporate identity. **Role-based access** across workspaces and APIs. **Audit trails** alongside Git history. **Self-hosting** with an MIT-licensed core when data must stay in your perimeter. **Privacy-conscious docs hosting** with no third-party analytics or tracking cookies, and first-party page view analytics that never store IP addresses ([Docs privacy](/products/docs/privacy)). **MCP guardrails** so you choose which endpoints become agent tools, set search vs execute modes, and apply API auth per installation ([MCP](/products/agent/mcp)).
**1M+**
Developers Use Scalar
**50k+**
APIs on Scalar
**10MM+**
OSS Installs
## Ready to Modernize your API Lifecycle?
We're committed to enabling developers and companies to practice the highest of API industry standards.
[Book a Demo](https://scalar.cal.com/forms/142d1e65-97d2-4d03-94c3-96f98ddef95a) [Get Started](https://dashboard.scalar.com/register)
# Company
Building on a great API is one of the best feelings in software: every desired interface is right there and it all just works. Building on a bad one is the opposite: out-of-date docs, no SDK in your favourite language and no MCP server. We started Scalar to solve this.
As a small team (10) of engineers and designers, we wear a lot of hats and obsess over our craft. We think every company deserves Stripe-level docs, SDKs, and MCP servers from day zero, not just the ones with a platform team to build them.
[Explore Careers →](#careers)
## Our Story
Three things drive everything we build: accessibility, API-first, and open-source. Accessibility is about that "just works" feeling. When integration is easy, people build — so we obsess over the path to the first successful request.
API-first is how a business scales for what's coming. If your product is built around a clean API, it's ready for whatever consumes it next, including Agents & LLMs.

Open-source is in our DNA. [Twelve years](https://github.com/jasperproject/jasperproject.github.io/pull/15) ago I built a Twitter module for Jasper, an open-source voice assistant — my first real contribution to something bigger than myself. It got merged, and that feeling of being part of something people actually used never left.
Today our whole team contributes to and maintains repositories across the open-source API ecosystem, and we care about that work meticulously. Done right, open-source is transparent, it builds the shared standards everyone relies on, like OpenAPI, it accelerates innovation, and it brings people together. It's core to who we are, not a marketing line.
We're fans of show-don't-tell, so the best intro to Scalar is using it: the docs you're reading now, our SDKs and API Client, the Agent/MCP servers for chatting with APIs, and our GitHub for everything open-source.
We are the API company, giving you industry-best interfaces for your APIs so you don't have to build the undifferentiated work yourself.
## Our Team

[Marc Laventure](https://www.linkedin.com/in/marc-laventure/)
CEO / Co-Founder

[Cameron Rohani](https://www.linkedin.com/in/cameron-rohani-5ba99a99/)
Co-Founder

[Hans Pagel](https://www.linkedin.com/in/hans-pagel-35303a18a/)
Co-Founder

[Peter McGrath](https://www.linkedin.com/in/peter-mcgrath-cpa-795470111/)
COO

[Geoff](https://www.linkedin.com/in/geoffgscott/)
Head of Engineering

[Amrit](https://www.linkedin.com/in/amrit-kahlon/)
Staff Software Engineer

[Brynn](https://www.linkedin.com/in/bnhwkr/)
Designer / Developer

[Redis](https://www.linkedin.com/in/redis-stasa-14b2aa24a/)
Senior Software Engineer

[Join Us](#careers)
We are hiring
## Our Investors

Trevor Oelschig Managing Director, General Catalyst

Steve Jang Managing Director, Kindred
Guillermo Rauch CEO, Vercel
David Cramer Founder, Sentry
Colin Sidoti Founder, Clerk
Paul Klein Founder, Browserbase
Koen Bok Co-Founder, Framer
Geige Vandentop Co-Founder, Streamyard
Sébastien Chopin Founder, Nuxt
John Phamous Design Engineer, Vercel
Kyle Parrish Early, Figma
Moe Amaya Founder, Operate
Ramtin Naimi Founder, Abstract
Tom Preston-Werner Founder, GitHub
Cassidy Williams Senior Director, GitHub
Soleio Designer × Investor
Jorn van Dijk Co-Founder, Framer
Andrew Miklas Founder, PagerDuty
Dan Briggs Co-Founder, Streamyard
Ben Lang Early, Notion
Pim De Witte Founder, General Intuition
Annie Luchsinger Founder, Breakers
## Careers
Engineering
[Senior / Staff Fullstack Engineer Europe, North America, Remote ](https://jobs.ashbyhq.com/scalar/aa017463-43c4-407c-b6c9-b59076f01d82)[Senior / Staff Platform Engineer Europe, North America, Remote ](https://jobs.ashbyhq.com/scalar/77ff0d8b-37ea-4185-b3fd-6f6cc64c08fd)[Senior / Staff Product Engineer Europe, North America, Remote ](https://jobs.ashbyhq.com/scalar/aa017463-43c4-407c-b6c9-b59076f01d82)
Sales
[Sales Development Representative San Francisco, CA ](https://jobs.ashbyhq.com/scalar/830eca96-dc30-46bd-a0f1-951c0dcdd9ea)[Founding Solutions Engineer San Francisco, CA ](https://jobs.ashbyhq.com/scalar/274bf7b1-be2a-45e4-9910-eb9bbced8366)[Founding Account Executive San Francisco, CA ](https://jobs.ashbyhq.com/scalar/b1e4ce53-ab1c-486a-94a6-a639537a0344)
# Security
Scalar helps teams create API interfaces built for developers and agents, including API references, SDKs, API clients, and MCPs from a shared OpenAPI source. Scalar has received a SOC 2® Type 1 report on controls relevant to security and maintains GDPR-compliant privacy practices.
[View Trust Center](https://trust.scalar.com) [Contact security](mailto:support@scalar.com?subject=Security%20question)
## Trust and compliance
* **SOC 2 report:** Scalar has received a SOC 2 Type 1 report for controls relevant to security.
* **GDPR privacy:** Scalar publishes European privacy rights and data processing details in our [Privacy Policy](/legal/privacy-policy).
* **Trust Center:** Security documentation and compliance materials are available at [trust.scalar.com](https://trust.scalar.com).
## Access controls
Use Scalar as a controlled surface for API descriptions, SDK generation, MCP installations, registry workflows, and developer tooling.
* **Single sign-on:** SAML-based SSO keeps authentication tied to your organization's identity provider. Read the [SSO guide](/resources/sso/getting-started).
* **Role-based access:** Control what each team member can do with team roles. Read [User Management](/resources/user-management).
* **Private API interfaces:** Publish internal references, portals, and API workflows behind access controls while keeping public interfaces simple to share.
* **Git-native review:** Keep API description changes visible in the same review flow your engineers already use.
## Privacy
Scalar's hosted API interfaces are privacy-friendly by default, with only technically required cookies used for authentication and routing.
* **Technically required cookies only:** Scalar uses required cookies for authentication and subpath routing, not visitor profiling.
* **No third-party tracking:** Hosted docs carry no third-party analytics scripts or tracking cookies.
* **First-party analytics without IP addresses:** Docs sites count page views on Scalar's servers with a visitor pseudonym that changes daily. IP addresses are never stored, and each project can turn analytics off.
* **GDPR privacy rights:** European users can request access, correction, deletion, transfer, or withdraw consent through Scalar's privacy contact.
Read more in the [privacy notes](/products/docs/privacy).
## API lifecycle security
Scalar treats OpenAPI as a source of truth for developer docs, API clients, generated SDKs, MCP servers, and review workflows.
* **Auth-aware API descriptions:** Model API keys, bearer tokens, OAuth flows, and other security schemes directly in your OpenAPI document.
* **Rules and validation:** Add review gates and linting so API changes are caught before they reach consumers.
* **SDK generation:** Generate production-ready SDKs and CLIs from reviewed API descriptions. See the [SDK Generator](/products/sdk-generator/).
* **MCP guardrails:** Choose which endpoints become tools, decide search versus execute modes, and apply API auth per installation. See [MCP & Agent](/products/agent/).
* **Self-hostable foundation:** Run Scalar's open-source tooling in your own environment when your architecture requires it.
## Responsible disclosure
If you find a vulnerability, email [support@scalar.com](mailto:support@scalar.com?subject=Security%20vulnerability%20report). We will acknowledge your report, triage the issue, and keep you updated as we work through a fix.
# OpenAPI Documentation with Scalar
Scalar takes an OpenAPI document and turns it into an interactive API reference — and, from the same document, an API client, generated SDKs, and an MCP server. This page explains what happens to your OpenAPI document when you bring it to Scalar, which versions are supported, how the documentation stays in sync with the API, and what is open source.
If you are evaluating documentation tools around an existing OpenAPI document, this is the summary. The detailed guides are linked throughout.
## At a glance
| | |
| --- | --- |
| Input | OpenAPI 3.0, OpenAPI 3.1; Swagger 2.0 documents are upgraded on load |
| Output | Interactive API reference, API client, SDKs, MCP server — from one document |
| Renderer license | MIT, at [github.com/scalar/scalar](https://github.com/scalar/scalar) |
| Framework integrations | More than 35 — Express, Fastify, Hono, NestJS, Next.js, FastAPI, Django, Rails, Laravel, ASP.NET Core, Spring Boot, and more |
| Where it runs | Hosted on Scalar, self-hosted, or mounted inside your own application |
| Staying in sync | Automatic redeploys from Git or from the Scalar Registry |
| Price | Free hosted docs; Pro at $150/month with one SDK included; additional SDKs from $150/month each |
## What Scalar does with an OpenAPI document
Your OpenAPI document is the input for every interface Scalar produces:
- **An interactive API reference.** Every operation, schema, and example in the document is rendered as browsable documentation with code samples for popular HTTP clients and languages, and a "Test Request" button on every operation.
- **An API client.** A standalone, open-source client — desktop and web, offline-first, with environments, Postman-compatible scripting, and code generation for 40+ HTTP clients. It imports the same document your docs are built from.
- **SDKs.** The [SDK generator](../guides/sdks/getting-started.md) compiles the document into client libraries. `docs` is a build target alongside the language targets: one generation run emits the SDKs, a static API reference, and the exact augmented document both were produced from. The reference and the client libraries cannot describe different APIs, because they come from the same compiled document in the same run.
- **An MCP server.** Scalar spins up [MCP servers](../guides/agent/mcp.md) from your OpenAPI document, so AI agents can call the endpoints you choose to expose, with the authentication you configure.
The phrase "single source of truth" gets used loosely in this category. Here it is literal: the OpenAPI document is the artifact everything else is generated from, and there is no second copy to drift.
## OpenAPI 3.0, 3.1, and Swagger 2.0
Scalar renders documents that follow the Swagger 2.0, OpenAPI 3.0, or OpenAPI 3.1 specification. Swagger 2.0 documents are upgraded on load, so a legacy document works without a manual conversion step first.
The upgrade logic is itself an open tool: [`@scalar/openapi-upgrader`](../guides/openapi-upgrader/getting-started.md) converts Swagger 2.0 to OpenAPI 3.0 or 3.1 (with experimental support for OpenAPI 3.2), as an npm package or a one-line CLI command:
```bash
npx @scalar/cli document upgrade swagger.json --output openapi.json
```
Scalar also reads a set of [OpenAPI extensions](../openapi.md) — `x-codeSamples` for custom SDK snippets, `x-tagGroups` for sidebar grouping, `x-scalar-ignore` for hiding operations, and others — including extensions written by other tools such as Stainless and ReadMe, so a document generated elsewhere renders correctly without edits.
## How the documentation stays in sync
The reference updates whenever the OpenAPI document changes. There are a few ways to wire that up, documented in the [deployment guides](../guides/docs/deployment/automatic-deployment.md):
- **Git.** Keep the document in your repository and enable automatic deployment: every merge into your default branch republishes the docs. Preview deployments and a [GitHub Actions workflow](../guides/docs/deployment/github-actions.md) are available when you want more control.
- **The Registry.** If your docs reference an OpenAPI document from the [Scalar Registry](../guides/registry/getting-started.md), updating that Registry document also triggers the docs to publish again.
- **The CLI.** `npx @scalar/cli project publish` deploys from your terminal or any CI/CD environment, without granting repository access.
There is no step where documentation is written separately from the API description and then reconciled. The document changes; the reference follows.
## Runs inside the framework you already use
Scalar ships more than 35 framework integrations, so the reference can be mounted inside the application that serves the API, at whatever route you choose — instead of living only on a separate hosted site:
- **JavaScript and TypeScript**: Express, Fastify, Hono, NestJS, Next.js, Nuxt, AdonisJS, ElysiaJS, Hapi, Nitro, Platformatic, SvelteKit, Astro, Ts.ED
- **Python**: FastAPI, Django, Django Ninja, Flask
- **PHP**: Laravel
- **Ruby**: Ruby on Rails
- **.NET**: ASP.NET Core, Aspire
- **Java**: Spring Boot, Micronaut
- **Go**, **Rust** (Actix Web, Axum, warp), and **Elixir**
If your framework is not on the list, the plain [HTML integration](../integrations/html-js.md) is a single script tag:
```html
```
## Open source, precisely
The Scalar API reference renderer and the API client are MIT licensed, developed in the open at [github.com/scalar/scalar](https://github.com/scalar/scalar). You can run them offline, without an account, embed them in your own product, self-host them on any plan, or fork them outright. This is open enough that GitBook's interactive API explorer is [powered by Scalar](https://gitbook.com/docs/api-references/openapi) — another documentation company ships the component inside their own product.
To be precise about the boundary: the documentation stack is open source; the SDK generator is not.
## What it costs
Pricing is published in full on the [pricing page](https://scalar.com/pricing):
- **Free** — $0. Hosted OpenAPI docs, the built-in API client, viewer seats, and one SDK for APIs up to 25 endpoints.
- **Pro** — $150/month. Custom domains, Git Sync, Markdown and MDX guides, hosted MCP servers, automated GitHub workflows, 5 editor seats, and one SDK for APIs up to 100 endpoints.
- **Business** — $600/month. Everything in Pro, plus SSO, subpath hosting, 10 editor seats, and APIs up to 250 endpoints.
- **SDKs** — one included with every plan; additional SDKs start at $150/month each, with volume discounts as you add more.
- **Enterprise** — custom pricing, with SAML, RBAC, and SLAs.
The MIT-licensed renderer is free regardless of plan, on your own infrastructure.
## Where to go next
- [Scalar Docs](../guides/docs/getting-started.md) — hosted documentation sites with guides, versions, and Git Sync
- [API Reference quickstart](../guides/api-references/getting-started.md) — render an OpenAPI document in a few lines of code
- [Create a free account](https://dashboard.scalar.com/register) — hosted docs from your OpenAPI document, at $0
---
*This page describes Scalar's products as of July 2026, based on Scalar's own documentation and source code. If you find something wrong or out of date, please [open an issue](https://github.com/scalar/scalar/issues) and we will correct it.*
# API Documentation for Developer Tools Companies
If you sell to developers, your API documentation is not a support artifact. It is the first product surface most of your users touch, and for many of them it is the deciding one. This page explains how developer tools companies use Scalar to keep docs, SDKs, and an interactive API client in sync with one OpenAPI document — and where the boundaries of that claim are.
This page is written by Scalar. Every product claim on it is backed by our own documentation, and we link the relevant guide for each one. If something here is wrong or out of date, [open an issue](https://github.com/scalar/scalar/issues) and we will fix it.
## At a glance
| | Scalar |
| --- | --- |
| Source of truth | One OpenAPI document (3.0 or 3.1; Swagger 2.0 upgraded on load) |
| Docs update via | [Git sync](../guides/docs/integrations/github.md): commit, merge, published |
| Preview before merge | [Preview deployment per pull request](../guides/docs/deployment/preview-deployments.md), with a PR comment link |
| SDK targets | TypeScript, Python, Go, Java, Kotlin, Ruby, CLI generally available; more experimental |
| Code samples in docs | Generated per SDK, injected as `x-codeSamples` into your reference |
| Try-it-out | Open-source API client built into the reference |
| Docs renderer license | MIT, self-hostable on any plan |
| Framework integrations | 35 (Express, Fastify, Hono, NestJS, Next.js, FastAPI, and more) |
| Pricing | Free tier; Pro $150/month with one SDK target included; additional targets $150/month — [published](../guides/pricing.md) |
## The problem, specifically
Developer tools companies ship API changes weekly, sometimes daily. That cadence breaks documentation in a predictable sequence:
1. The API changes, and the OpenAPI document is updated — or it is not, which is its own problem.
2. The docs site is a separate system, so someone has to carry the change over. It lags.
3. The code samples in the docs were written by hand months ago. They still show the old parameter names.
4. The SDKs were generated (or written) against an earlier version of the API. They drift too, on their own schedule.
Each of these is a small failure. Together they mean the developer evaluating your product hits a broken example in the first ten minutes, and your docs — the thing that was supposed to acquire developers — becomes a maintenance queue instead.
The fix is structural, not editorial: everything downstream of the API has to regenerate from the same document, in the same workflow your engineers already use.
## How Scalar handles it
**The API reference renders from your OpenAPI document, and updates through Git.** Scalar Docs [connects to GitHub](../guides/docs/integrations/github.md) through a GitHub App scoped to the repositories you select. It reads your files, opens pull requests, and publishes when you merge. Your OpenAPI document and your Markdown guides live in your repository, reviewed like any other code. There is no separate CMS to keep in sync.
**Every pull request gets a preview.** When you open a PR, Scalar [creates a preview deployment](../guides/docs/deployment/preview-deployments.md) and can post a comment with a direct link, so reviewers see the rendered docs — not a diff of Markdown — before anything ships. If your project is not connected to GitHub, the CLI publishes previews too: `npx @scalar/cli project publish --slug your-docs --preview`.
**SDKs follow the same document.** The [SDK generator](../guides/sdks/index.md) points each SDK at an exact version of your API document or at a semver range such as `^1.2.0`. When a matching document changes, Scalar mints a new SDK version, rebuilds every target, and opens pull requests against your repositories. One commit to your API updates all of your clients.
**The code samples in your docs come from the generated SDKs.** Generation injects samples into your OpenAPI document as `x-codeSamples`, and the reference renders them. The snippet a developer copies out of your docs is derived from the same document the SDK was built from, so it does not rot independently. Examples you curated by hand are preserved.
**Developers can call the API without leaving the page.** The reference includes Scalar's open-source API client, so "try this endpoint" is a click, not a context switch to a separate tool. The client also ships standalone — desktop and web, MIT licensed, offline-first.
What Scalar does not do: it will not keep your OpenAPI document itself accurate. If your engineers do not update the description when the API changes, no tool downstream can save you. Scalar removes every sync step after that one.
## Why this fits developer tools companies in particular
Scalar's customer profile is companies whose API *is* the product, or is close to it: public APIs, developer-facing surfaces, teams that treat API developer experience as a competitive input rather than a compliance task. Some public examples:
- **[Clerk](https://clerk.com/docs/reference/frontend-api)** — authentication and user management for the modern web. Their Frontend API reference runs on Scalar.
- **[PAR Technology](https://developers.partech.com)** — restaurant and retail software. PAR [migrated its developer portal to Scalar](../guides/customers/partech.md) to modernize a docs-as-code workflow tied to GitHub, with pull-request-based reviews and automatic publishing on merge. The full story is worth reading if your setup looks similar.
- **[Bobcat](https://developer.bobcat.com/)** — equipment manufacturer with a public developer portal on Scalar.
- **[Thomson Reuters](https://developers.thomsonreuters.com/pages/api-reference/19232a0d-5cf9-53a9-a215-efe481550832)** — API references inside their developer portal.
One more data point: [GitBook's interactive API explorer is powered by Scalar](https://gitbook.com/docs/api-references/openapi). The reference component is open enough that another documentation company ships it inside their own product.
And scalar.com itself — this page included — is built and hosted on Scalar Docs from a single `scalar.config.json`. We do not maintain a separate marketing stack, so the workflow described above is the one producing what you are reading.
## The feature list that matters for this audience
Everything below is documented; each link goes to the guide.
- **[Git sync](../guides/docs/integrations/github.md)** — the Scalar GitHub App reads your files, opens pull requests, and publishes on merge. Access is limited to repositories you select. Scalar describes this as two-way: content flows from your repository into the docs, and edits made through Scalar land back as commits and pull requests attributed to you.
- **[Preview deployments](../guides/docs/deployment/preview-deployments.md)** — a rendered preview for every pull request, with optional PR comments linking to it.
- **[Versioning](../guides/docs/configuration/versions.md)** — multiple documentation versions under one domain with a version selector, each with its own navigation. Useful when v1 and v2 of your API coexist for years, which for developer tools companies they usually do.
- **[Custom domains](../guides/docs/configuration/domains.md)** — `docs.yourcompany.com` via a CNAME to `dns.scalar.com`, with HTTPS provisioned automatically. Requires the Pro plan.
- **OpenAPI 3.0 and 3.1** — both supported, and Swagger 2.0 documents are [upgraded on load](../openapi.md). You do not need to modernize your descriptions before adopting the platform; PAR ran this exact incremental path.
- **35 framework integrations** — if you want the reference mounted inside your own application rather than hosted, there are [integrations](/products/api-references/integrations) for Express, Fastify, Hono, NestJS, Next.js, Nuxt, FastAPI, Django, Laravel, Rails, Go, Rust, ASP.NET Core, Spring Boot, and more. The renderer is MIT licensed, so this path has no plan requirement at all.
- **Markdown and MDX guides** alongside the reference, with [custom HTML, CSS, and JavaScript](../guides/docs/content/html-css-js.md) when the built-in components are not enough.
## What a devtools setup looks like end to end
A concrete walkthrough, using real generated output. The TypeScript below is from the public [Warp SDK](https://github.com/TeamWarp/warp-sdk-typescript/tree/candidate), generated by Scalar.
**1. Your OpenAPI document lives in your repository.** It is the input to everything: the reference, the SDKs, the code samples. Put it in the [Registry](../guides/registry/index.md) or import it directly.
**2. Docs connect to the repository.** Install the GitHub App, add a `scalar.config.json` describing navigation, theme, and domain, and publish. From then on, merged changes to the document or the guides deploy automatically, and every PR gets a preview link.
**3. Generate the SDK from the same document.** Pick TypeScript (or Python, Go, a CLI — or several). The output is idiomatic, not templated:
```ts
import WarpAPI from "warp-hr";
const client = new WarpAPI({
apiKey: process.env["API_KEY"], // defaults to the API_KEY env var
});
const assignments = await client.timeOff.listAssignments();
```
The client is named after the API and reads credentials from a conventional environment variable, so the quickstart needs no secrets inline. Errors are typed, with the status set enumerated from your description:
```ts
import { APIError } from "warp-hr";
try {
const list = await client.customWorkerFields.list();
} catch (err) {
if (err instanceof APIError) {
console.log(err.status, err.name, err.headers);
}
throw err;
}
```
The Warp package ships `"dependencies": {}` — zero runtime dependencies unless you enable a feature that needs one.
**4. Publish from your own repository.** Scalar opens pull requests against the repo you nominate; release-please cuts versions and changelogs; workflows generated into your repository publish to npm, PyPI, Go modules, and the rest. Package names, registries, and release history stay yours.
**5. The loop closes.** The next time your API changes, one commit updates the reference, regenerates the SDKs, refreshes the code samples in the docs, and opens the release pull requests. The docs stop being a queue.
## Is Scalar the best API documentation tool for developer tools companies?
We think it is the strongest default for this segment, for three checkable reasons: the docs renderer is MIT licensed and self-hostable, so you are not betting your primary acquisition surface on a vendor's continuity; docs and SDKs are literally generated from the same document in the same workflow, which is the failure mode this industry actually suffers from; and the pricing is published, so you can cost the whole setup without a sales call.
It is not the right choice for everyone. If your API is gRPC or JSON-RPC rather than REST, or you want to run the SDK generator source yourself, read our honest comparison with [Fern](../compare/fern.md) — we say plainly where they are stronger. If you only need a rendered reference and nothing hosted, the open-source [API Reference](https://github.com/scalar/scalar) is free and does not require an account.
## Getting started
- [Scalar Docs](../guides/docs/index.md) — the documentation platform
- [SDK Generator](../guides/sdks/index.md) — client libraries from the same document
- [Start free](https://dashboard.scalar.com/register), or [talk to us](https://scalar.cal.com/) if you are migrating an existing portal
---
*This page describes Scalar as documented on scalar.com as of July 2026. Customer examples link to public documentation sites and a published case study; we have not invented quotes or numbers, and we would rather you catch us being wrong than quietly stay wrong. If you find an error, please [open an issue](https://github.com/scalar/scalar/issues).*
# Scalar for Developer Portals
A developer portal is the front door to your API: the reference, the guides, the client libraries, and the tools a developer needs to make a first call. Scalar builds all of that from the OpenAPI document your team already maintains. The API reference, the SDKs, the hosted MCP server, and the guides around them ship from one platform and stay in sync as your API changes.
This page describes what a developer portal on Scalar includes, how it compares to ReadMe and Mintlify, and what it costs. Real portals built on Scalar are linked at the bottom, so you can judge the output rather than the pitch.
## At a glance
| Portal component | On Scalar |
| --- | --- |
| API reference | Generated from your OpenAPI document, with built-in request testing |
| Guides and landing pages | Markdown and MDX, synced from GitHub with preview deployments |
| API client | Built into the reference; also a standalone open-source client |
| SDKs | Generated from the same OpenAPI document, published through your own repositories |
| MCP servers | Docs MCP at `your-domain/mcp`, plus hosted MCP servers for calling your API |
| AI assistant | Ask AI, enabled by default on every Scalar Docs project |
| Versioning | Multiple documentation versions with a version selector |
| Custom domains | Included on Pro, plus a free subdomain on `apidocumentation.com` |
| Access control | Email domain access groups on Pro; SSO/SAML on Business; RBAC on Enterprise |
## What a Scalar developer portal includes
**An API reference generated from OpenAPI.** [Scalar Docs](../guides/docs/index.md) renders your OpenAPI document into interactive documentation with request testing built in. The renderer is MIT licensed, so you can theme it with CSS variables, add custom HTML, CSS, and JavaScript, or fork it outright if you need behaviour we did not anticipate.
**Guides written in Markdown or MDX.** Product guides, tutorials, and landing pages live beside the reference in one navigation. Content is pulled from GitHub, every pull request gets a preview deployment, and merges deploy automatically — or you publish from the CLI. All of scalar.com, including this page, is built with Scalar Docs from a single `scalar.config.json`.
**A built-in API client.** Developers test endpoints directly in the reference — no separate tool to install, no context switch. Scalar also ships a standalone, open-source [API client](../guides/app/index.md) for desktop and web, with environments, collections, and Postman-compatible scripting, so the testing workflow developers start in your docs continues after they leave them.
**SDKs in the languages your users ask for.** The [SDK Generator](../guides/sdks/index.md) produces idiomatic, type-safe client libraries — TypeScript, Python, C#, Java, PHP, Go, Ruby, Rust, Swift, and Dart — from the same OpenAPI document that renders the reference, and publishes them from your own repositories through pull requests you control.
**MCP servers for AI clients.** Scalar exposes [two MCP surfaces](../guides/agent/index.md): a Docs MCP at `your-docs-domain/mcp` that lets tools like Cursor and Claude Code search and read your published documentation, and hosted MCP servers that let AI clients call the API endpoints you select, with delegated authentication so agents never receive your upstream credentials.
**Ask AI.** An AI assistant is enabled by default on every Scalar Docs project. It searches your published documentation and combines information from multiple pages into a short, sourced answer — no setup required.
## One document keeps it in sync
Most portal stacks assemble these pieces from separate vendors: a docs platform, an SDK vendor, an API client, an MCP gateway. Each one holds its own copy of your API description, and each copy drifts.
On Scalar, the single source of truth is literal. In the SDK generator, `docs` is a build target alongside the language targets — one generation run emits the SDKs, a static API reference, and the exact OpenAPI artifact the SDKs were generated from. Your reference and your client libraries cannot describe different APIs, because they are produced from the same compiled document in the same run. With Git sync, one commit to your OpenAPI document updates the reference, regenerates the SDKs, and refreshes the MCP server together.
## Who it is for
- **API-first companies** whose product is the API, and whose portal is the product page, the manual, and the toolbox at once.
- **Developer tools companies** where documentation quality is judged by developers who read a lot of documentation.
- **Teams shipping public APIs** that need the surrounding infrastructure: multiple documentation [versions](../guides/docs/configuration/versions.md) with a version selector, [custom domains](../guides/docs/configuration/domains.md), and access control — from email domain access groups on Pro to SSO/SAML on Business and RBAC on Enterprise.
## How it compares to ReadMe and Mintlify
Both are credible choices for a developer portal, and the honest comparison is about product shape rather than quality.
**ReadMe** specializes in developer hubs with real API usage data inside them. Their [Developer Dashboard](https://docs.readme.com/main/docs/developer-dashboard) shows who is calling your API, personalized docs surface each developer's own API keys and logs, and their [API metrics](https://readme.com/metrics) report call volume, endpoint usage, and errors. Scalar does not have an equivalent of those API analytics dashboards today. ReadMe offers a per-project [MCP server](https://docs.readme.com/main/docs/readmes-mcp-server) for searching and reading docs content, and their [`api`](https://api.readme.dev/docs/getting-started) tool generates TypeScript SDKs; Scalar's SDK generator covers ten languages with publishing to package registries, and its hosted MCP servers can call your API with delegated authentication.
**Mintlify** focuses on documentation polish: strong theming, localization across 30+ locales, and unlimited editor seats on a flat price. Mintlify does not generate SDKs — it renders code samples from third-party generators such as [Speakeasy](https://www.mintlify.com/docs/integrations/sdks/speakeasy) and [Stainless](https://www.mintlify.com/docs/integrations/sdks/stainless). We publish a detailed [Scalar vs Mintlify](../compare/mintlify.md) comparison.
**Scalar** is the option in this group that also generates SDKs and hosts MCP servers from the same OpenAPI document that renders the reference, ships a standalone open-source API client alongside the docs, and licenses the documentation renderer under MIT so the portal layer is yours to keep.
## Pricing
Scalar publishes its prices, so you can work out what a portal costs without talking to sales. Full details are on the [pricing page](../guides/pricing.md).
- **Free ($0)** — hosted OpenAPI docs, the built-in API client, one SDK for APIs up to 25 endpoints, and one editor seat. Enough to put a real reference online.
- **Pro ($150/month)** — the full developer portal: custom domains and subdomains, Git Sync, Markdown and MDX, guides, versions, landing pages, email domain access control, and hosted MCP servers. Includes 5 editor seats, access groups, and one SDK for APIs up to 100 endpoints; additional SDKs are $150/month each.
- **Business ($600/month)** — everything in Pro, plus SSO/SAML and subpath hosting, 10 editor seats, APIs up to 250 endpoints, and additional SDKs priced by size: $150/month each for up to 100 endpoints or $600/month each for 101–250 endpoints, with volume discounts. The included SDK applies to the most expensive band first. See [SDK pricing](../guides/pricing.md) for details.
- **Enterprise (custom)** — adds RBAC, priority support with SLAs, migration services, and a dedicated Slack or Teams channel. [Book a demo](https://scalar.cal.com/).
## Portals built on Scalar
The clearest way to evaluate a portal platform is to use a portal built on it:
- **[Bobcat developer portal](https://developer.bobcat.com/)** — the American manufacturer of farm and construction equipment runs its public developer portal on Scalar.
- **[Thomson Reuters developer platform](https://developers.thomsonreuters.com/pages/api-reference/19232a0d-5cf9-53a9-a215-efe481550832)** — API references for the provider of software and decision tools for legal and accounting companies.
- **[Clerk](https://clerk.com/docs/reference/frontend-api)** — the authentication and user management platform renders its API reference with Scalar.
- **[PAR developer portal](https://developers.partech.com)** — PAR Technology's portal for the Punchh Loyalty platform, migrated from a legacy platform to Scalar with a docs-as-code workflow in GitHub. The full story is in the [PAR case study](../guides/customers/partech.md).
## Get started
[Start free](https://dashboard.scalar.com/register), review [pricing](../guides/pricing.md), or [book a demo](https://scalar.cal.com/) and we will walk through your portal with you.
---
*This page describes Scalar's developer portal capabilities as of July 2026, based on Scalar's own documentation and pricing. Claims about ReadMe and Mintlify link to their public documentation. If you find something wrong or out of date, please [open an issue](https://github.com/scalar/scalar/issues) and we will correct it.*
# How PAR Technology Corporation Enhanced Its Developer Experience With Scalar: a Modern, Open Standards API Management Platform
## Overview
PAR Technology Corporation (“PAR”), [partech.com](https://partech.com/), a global provider of software and solutions for restaurant and retail brands, maintains a unified developer experience through its public-facing [PAR Developer Portal](https://developers.partech.com), where developers and partners can access documentation and related technical resources for various PAR APIs.
In 2025, PAR set out to modernize the foundation of this portal to ensure long-term reliability, improve the developer journey, and align with open, future-proof API standards. As part of this initiative, the PAR Product Operations organization evaluated a range of modern documentation and API-forward platforms.
Ultimately, PAR selected Scalar, [scalar.com](https://scalar.com), as the best aligned partner with its long-term developer experience strategy.
## Why PAR Pursued a Platform Update
The PAR Developer Portal serves as the main hub for partners integrating with the PAR Punchh Loyalty platform, including Online Ordering, POS, Mobile APIs, and Webhooks. Ensuring that the portal remains intuitive, publicly accessible, and easy to navigate is essential for customers building integrations across the PAR ecosystem.
As part of a broader modernization effort, PAR sought a platform that could:
- Strengthen support for open standards, especially the OpenAPI family
- Preserve and enhance its docs-as-code workflow tied to GitHub
- Offer a modern, interactive developer-facing UI
- Provide flexibility for incremental upgrades to API specifications and supporting documentation
- Improve discoverability and reduce friction within the documentation experience
- Provide a structural framework to enable additional PAR business units to onboard their content
A streamlined, stable long-term foundation was critical to support the organization’s priorities, tight migration timeline, and the need to maintain continuity for external developers during the migration to Scalar.
## Why Scalar Was the Right Fit
Scalar is a modern API platform built around the OpenAPI standard, offering interactive documentation, SDK/code sample generation, and an open-source API client — all within a contemporary interface designed to make API exploration easier and more intuitive for developers.
> "When we first spoke with the team at PAR, their long-term vision for their developer portal resonated immediately: a portal built on open standards, delivering a modern developer experience, with a foundation that could grow with them as they onboard more teams and content,” said Marc Laventure, CEO and Co-Founder of Scalar. “It was clear that what they were looking for aligned perfectly with what Scalar was built to do. Working through the migration and seeing the portal come together has been incredibly rewarding, and we're proud to be part of PAR's developer experience going forward."
Several aspects of Scalar aligned especially well with PAR’s requirements:
### Open-Standards Foundation
Scalar supports Swagger 2.0 and OpenAPI 3.x specifications out of the box. This compatibility enables PAR to maintain its existing API specifications while gradually modernizing to newer formats when ready — without forcing a disruptive wholesale conversion.
### Seamless Documentation Workflow
Scalar’s documentation system allows PAR to maintain source content in GitHub repositories and publish to Scalar using an automated process. This keeps content creation within PAR’s established docs-as-code workflow; developers can author content in the same tools they already use, and Scalar generates the polished UI using a build/publish operation triggered by GitHub commits. This enables developers to use pull requests for their content reviews. Scalar provides a tool that enables developers to fully preview changes in real time while editing their code in the GitHub repositories, so they can see how their content will appear in the developer portal before it gets published. After merging the code changes, the updates are automatically published to the developer portal.
### Modern, Developer-Friendly UI
Scalar provides a responsive API reference interface with multi-language code samples and a robust search experience. These qualities directly support PAR’s goal of shortening developers’ time to first call and reducing friction for partners learning the APIs. Scalar also enables a flexible information architecture by layering multiple sub-projects into the root developer portal project. Each project can be associated with a unique GitHub repository.
### Future-Proof Ecosystem Support
When evaluating options for hosting the PAR Developer Portal platform, a key consideration was platform extensibility. PAR wanted flexibility when incorporating ancillary educational and training materials into the overall developer portal experience, such as Postman collections, interactive sample applications, and generative AI chatbots. The Scalar UI can accommodate and embed customized elements for a more unified experience, reducing the need to jump to external tools.
### White-Glove Support
As an Enterprise-level customer, PAR has access to hands-on, priority support with direct access to Scalar’s engineering talent. Reduced friction and decreased response time have helped boost productivity, enabling quicker roll-out of new features and enhancements and resolution of issues. Scalar’s team took an active role in facilitating the migration from PAR’s legacy developer portal platform to the Scalar platform. This included help with setting up the project framework in GitHub as well as adding redirect rules to ensure existing links would still work.
> "When migrating to Scalar from PAR's legacy developer portal platform, we needed to move quickly as our renewal deadline was approaching," said Brendan McInerney, Sr. Manager of Product Operations and Documentation at PAR Technology. "After weighing the costs and time required to complete the migration, Scalar's team was able to jump in on short notice and handle the migration logistics for us. This was a huge relief as we couldn't dedicate sufficient in-house resources to meet our tight timeframe. Scalar's flexibility and expertise not only enabled us to complete the cut-over to the new platform on time, but we also had time for post-migration testing. This continued collaboration with Scalar has positioned us well to drive new features and enhancements into the PAR Developer Portal."
> “Working closely with the PAR team throughout the migration was a great experience,” said Bruno Silva, Founding Engineer at Scalar. “They came in with clear goals and a deep understanding of what their developers needed, which made the collaboration seamless. Their high standards mirror our own commitment to delivering a top-of-the-line developer experience. When both sides hold themselves to that bar, it shows in the final product, and I think the PAR Developer Portal is a great example of that.”
## Enhancements to PAR Developer Portal
With Scalar now powering key parts of the experience, PAR’s public developer portal benefits in several ways.
### A More Consistent and Accessible Developer Journey
The portal maintains its base URL — [developers.partech.com](https://developers.partech.com/) — while offering clearer navigation and removing unnecessary login friction for publicly accessible content. This ensures that developers can reach API documentation quickly and reliably.
### Modernized API Reference Experience
Scalar’s interactive API reference brings a more intuitive way for developers to explore PAR APIs. A cleaner layout and richer code generation capabilities help users understand endpoints faster and experiment more confidently.
### Stronger Integration With PAR’s Developer Ecosystem
The updated developer portal is tightly connected with other developer-facing resources like:
- PAR Postman collections, enabling hands-on API exploration
- PAR sample applications offering payload generators, validators, and other utilities for Punchh integrations
- PAR generative AI assistant/chatbot that enables users to ask questions and receive an answer based on PAR’s proprietary developer portal content
This creates a smoother experience for developers transitioning between API documentation, code examples, Postman collections, and tool-assisted workflows.
### Long-Term Stability and Future Readiness
Because Scalar supports multiple versions of the OpenAPI spec simultaneously, PAR can evolve its APIs incrementally. There’s no rush to migrate legacy specs — teams can modernize on their own timeline with zero disruption to external developers.
> "As we migrated from PAR's legacy developer portal to Scalar, our objective extended beyond productivity gains and modernization," said Josh Schoonmaker, SVP of Product at PAR Technology. "We were equally focused on moving to a more cost-effective, scalable, and extensible platform. Scalar's flexibility—particularly its strong support for OpenAPI standards—positioned us to move faster and innovate with greater confidence. As we continue to integrate AI-driven tools and capabilities, Scalar enables our developer ecosystem to evolve rapidly and consistently deliver meaningful value."
## Results
By adopting Scalar, PAR aims to achieve measurable improvements in the developer experience:
- A more interactive, intuitive, and modern API reference
- A leaner workflow for content authors, fully aligned with GitHub
- Greater discoverability, with simplified navigation and public access
- Stronger integration with the PAR developer ecosystem
- A flexible foundation ready to support future iterations of OpenAPI, new API surface areas, and additional PAR business units
Overall, PAR’s goal with Scalar is to deliver a more polished, developer-friendly, and resilient developer portal that better supports development partners.
## Conclusion
PAR’s shift to Scalar reflects a strategic investment in open standards, developer productivity, and long-term platform stability. By adopting a technology that fits its existing workflows while enabling modern interaction patterns, PAR has positioned [developers.partech.com](https://developers.partech.com/) as a future-ready hub for API innovation across the organization.
# Accelerating Warp's AI-Native HR Platform with Scalar
Generated SDKs [ Go ](https://github.com/TeamWarp/warp-sdk-go)[ TypeScript ](https://github.com/TeamWarp/warp-sdk-typescript)[ Python ](https://github.com/TeamWarp/warp-sdk-python)[ CLI](https://github.com/TeamWarp/warp-cli)

Warp is building AI-native employee management for fast-growing companies — and betting that everything in the product should be reachable by API. When their SDK vendor told them the product was being discontinued, they moved all four surfaces to Scalar: every language at parity, no breaking changes, and not one customer who had to be told.
> “The best part has been how little I think about SDKs. A few clicks set up every language to parity with what we had, with no breaking changes — which was huge for us.”
>
> **Adam Rankin**, CTO, Warp
## An HR platform built to be called
Warp handles everything from hiring an employee through paying them: payroll, benefits, MDM, application access, authentication, time off, shift tracking, onboarding, offboarding, and staying compliant everywhere the company operates. The pitch is AI-native employee management — agents on the back end keeping customers compliant, and a product that will take a PDF of a company policy and turn it into working configuration rather than making someone fill in a long form.
The part that matters here is what they decided to do with the platform itself.
> “Everything that can be done in our app by clicking buttons can just be exposed via API — or whatever, bring your own agent. In our space, no one’s really done that in a first-class way. It’s all sort of an afterthought.”
So Warp made the API free on every tier.
> “Just open it up and see what people build — as opposed to, you’ve got to hop on a sales call to even know what’s possible.”
## Three kinds of developer showed up
> “It’s a pretty new offering and we’re already seeing a lot of different use cases.”
The API is young, and the demand has already split into three shapes — one of which barely existed as a category two years ago.
* **Running the company from an agent.** Customers who want to connect their Claude to everything: building reports, pulling data, sending an employee invite or signing an offer — all without opening the app.
* **Embedded payroll.** Partners embedding full payroll services inside their own product. The platform play.
* **Automating company messaging.** Warp sends a webhook when someone requests time off; a customer builds a Discord bot to surface it. “These days an agent is probably writing that.”
There is also a fourth answer Warp hears constantly in sales calls, and it says something about where the market is: we don’t really know what we want to build, we just want an API to see what we can build.
## Needing a new home for the SDKs
> “One day they basically sent us an email: we’re shutting down, we’re discontinuing. Our product is end of life in six months. So we were looking for alternatives.”
Warp had been generating their client libraries with a commercial vendor. That arrangement ended on the vendor’s timetable, not Warp’s, and the team had a fixed window to find a replacement, move four surfaces, and do it without disturbing the developers already integrated against them.
Building the generator in-house was the obvious alternative, and Adam has a short answer for the people who suggest it.
> “Everyone’s like, ‘oh, you could just do that yourself.’ It’s like — no. I don’t actually feel like setting up a whole generator for every language. We’re not an SDK company. We’re a payroll company, and we just want SDKs to work well.”
## He tried the build anyway
> “I don’t want a billion lines of slop generating my SDK.”
Before moving, Adam did what most engineering leaders would now do first: he pointed a coding agent at the problem and asked it to reproduce the SDKs in the same shape. It sort of worked.
> “I ended up with something that just seemed really brittle and was taking my time. And even a little bit of my time is not worth maintaining that when we have features to ship and customers to make happy.”
The alternative was a permanent line item. Asked what running SDKs properly in-house would have cost, Adam put a number on it immediately:
> “We’d have someone working on developer products, probably 50% of their time. That’s expensive. And we just haven’t had to have that at all.”
## A migration nobody noticed
> “No one asked. No one needed to know.”
Warp had real developers on the existing libraries. That made the constraint tighter rather than looser: a group of integrators is exactly the group you cannot afford to break. Every language came across at parity with what Warp already had, and existing users upgraded their SDK without changing a line.
**Results:** every language at parity · no breaking changes · no customer communication required · set up in a few clicks
## More than the libraries
> “Figuring out what more our OpenAPI could do that we didn’t even know.”
The part Warp didn’t expect was what the move taught them about their own spec. Working through the Scalar docs and the OpenAPI extensions surfaced capabilities in their schema they hadn’t been using — which matters more than usual for a company whose stated goal is that every button in the product has an API behind it.
> “Setting up automations, the OpenAPI extensions have been really awesome — figuring out what more our OpenAPI could do that we didn’t even know.”
> “The best part has been how little I think about SDKs. We’re not an SDK company. We’re a payroll company, and we just want SDKs to work well.”
>
> **Adam Rankin**, CTO, Warp
# Brand Guidelines
Everything you need to reference Scalar in your project, logos, wordmark, icon, and brand colors.
[Download brand assets ](/brand/scalar-brand-assets.zip)[Get in touch](mailto:support@scalar.com)
---
## Naming
"Scalar" is a single word, always spelled with a capital _S_. It is the brand name of both our company and our platform, not "Scalar app" or "scalar.com". Refer to the platform as **Scalar**.
Individual products are proper nouns and should be capitalized when referred to by their full name: **Scalar Docs**, **Scalar API References**, **Scalar Registry**, **Scalar SDKs**, and **Scalar API Client**. When the context is already clear, the short form is fine (Docs, API References, Registry, SDKs, API Client).
---
## Usage
Give our assets room to breathe. Scale them up or down, but never stretch, recolor, outline, rotate, or layer effects on top of them. Keep at least the height of the logomark as clear space on every side so the mark stands on its own.
These graphics are proprietary and protected by intellectual property laws. Please do not alter the files, imply a relationship, affiliation, or endorsement by Scalar, or combine them with other marks without written consent. Have a question or need custom assets? [Get in touch](mailto:support@scalar.com).
---
## Wordmark
Prefer the Scalar wordmark whenever space allows. Monochrome usage is preferred, use the dark version on light surfaces and the light version on dark surfaces.

Dark on light
[SVG](/brand/scalar-wordmark-light.svg) [PNG](/brand/scalar-wordmark-light.png)

Light on dark
[SVG](/brand/scalar-wordmark-dark.svg) [PNG](/brand/scalar-wordmark-dark.png)
## Logomark
Use the logomark for tight layouts, logo-only grids, or places where text alongside the mark would feel cramped. The wordmark carries stronger brand recognition, so reach for it first when you have the room.

Dark on light
[SVG](/brand/scalar-logomark-light.svg) [PNG](/brand/scalar-logomark-light.png)

Light on dark
[SVG](/brand/scalar-logomark-dark.svg) [PNG](/brand/scalar-logomark-dark.png)
---
## Colors
Scalar is built around a high-contrast monochrome palette that works on both light and dark surfaces. Our product accents add color when there's a reason to, per product, per state, per moment. Click any hex value to copy it.
Scalar Ink RGB 27, 27, 27 #1B1B1BCopy Scalar Slate RGB 117, 117, 117 #757575Copy Scalar Pewter RGB 142, 142, 142 #8E8E8ECopy Scalar Paper RGB 255, 255, 255 #FFFFFFCopy Docs Blue RGB 0, 130, 208 #0082D0Copy Registry Green RGB 6, 144, 97 #069061Copy Client Orange RGB 255, 88, 0 #FF5800Copy SDK Purple RGB 82, 3, 209 #5203D1Copy
---
Need something that isn't here, or permission for a specific use case? Email and we'll help.
[Migrate off Stainless • Read more →](/resources/migration/stainless)
# API interfaces built for developers and agents
Create beautiful docs, SDKs and secure MCP servers from your API. Scalar keeps every interface in sync as your API evolves.
[Get Started](https://dashboard.scalar.com/register) [Book a Demo](https://scalar.cal.com/forms/142d1e65-97d2-4d03-94c3-96f98ddef95a)
SDK
index.ts main.py Main.java Main.kt main.rs
```typescript
import Profound from '@profoundai/client';
const client = new Profound({
apiKey: process.env['PROFOUND_API_KEY'], // defaults to the PROFOUND_API_KEY env var
environment: 'production',
});
const category = await client.organizations.categories.list();
console.log(category);
```
```python
import os
from profound import Profound
client = Profound(
api_key=os.environ.get("PROFOUND_API_KEY"),
)
category = client.organizations.categories.list()
print(category)
```
```java
import com.profound.api.client.ProfoundClient;
import com.profound.api.client.okhttp.ProfoundOkHttpClient;
ProfoundClient client =
ProfoundOkHttpClient.builder().apiKey(System.getenv("PROFOUND_API_KEY")).build();
var category = client.organizations().categories().list();
System.out.println(category);
```
```kotlin
import com.profound.api.client.ProfoundClient
import com.profound.api.client.okhttp.ProfoundOkHttpClient
import com.profound.api.models.organizations.categories.CategoryListParams
val client: ProfoundClient =
ProfoundOkHttpClient.builder().apiKey(System.getenv("PROFOUND_API_KEY")).build()
val category = client.organizations().categories().list(CategoryListParams.none())
println(category)
```
```rust
use profound_rust::*;
#[tokio::main]
async fn main() -> Result<(), Box> {
let client = ProfoundClient::builder()
.api_key(std::env::var("PROFOUND_API_KEY")?)
.build()?;
let response = client.organizations().categories().list().send().await?;
println!("{:?}", response);
Ok(())
}
```
Docs
 
Docs
 
SDK
index.ts main.py main.go warp.sh
```typescript
import WarpAPI from "warp-hr";
const client = new WarpAPI({
apiKey: process.env["WARP_API_KEY"], // defaults to the WARP_API_KEY env var
});
// Auto-paginating: the next cursor page is fetched as you iterate.
for await (const assignment of client.timeOff.listAssignments({ limit: 50 })) {
console.log(assignment.id, assignment.policy.name);
}
```
```python
import os
from warp import Warp
client = Warp(api_key=os.environ.get("WARP_API_KEY"))
# Auto-paginating: the next cursor page is fetched as you iterate.
for assignment in client.time_off.list_assignments(limit=50):
print(assignment.id, assignment.policy.name)
```
```go
package main
import (
"context"
"fmt"
"os"
sdk "github.com/TeamWarp/warp-go-sdk"
"github.com/TeamWarp/warp-go-sdk/option"
)
func main() {
client := sdk.NewClient(option.WithAPIKey(os.Getenv("WARP_API_KEY")))
iter := client.TimeOff.ListAssignmentsAutoPaging(context.Background(),
sdk.TimeOffListAssignmentsParams{Limit: sdk.Int(50)})
for iter.Next() {
assignment := iter.Current()
fmt.Println(assignment.ID, assignment.Policy.Name)
}
if err := iter.Err(); err != nil {
panic(err)
}
}
```
```bash
# Install from Homebrew, or run it with npx warp
brew install teamwarp/tap/warp
export WARP_API_KEY="wrp_live_..."
# Flags are typed from the OpenAPI parameters
warp time-off list-assignments --limit 50 --output table
# Every command speaks JSON too, so it composes
warp time-off list-assignments --output json | jq '.data[].policy.name'
```
## Take their word for it
**“After years of helping enterprises implement API strategies at SmartBear, I can confidently say Scalar is what the industry has been waiting for.**
The strict OpenAPI compliance, robust CLI/API registry, and seamless CI/CD integration solve the exact pain points I watched customers struggle with daily. This is the modern API platform developers deserve.”
Michael, Former Solutions Architect @ Smartbear
“One of my most recent favorites is a in-browser ad hoc testing UI called Scalar.
One of the things that I really love about Scalar, it's got this modern UI experience, and it provides **built-in test generation code for a variety of targets, from cURL to HttpClient in C#.**”
Captain Safia, Engineer @ Microsoft ASP.NET
“Scalar's ‘golden ticket’ is… Scalar!
**They are (in my own words) building a product ecosystem for API design, docs, testing, and governance** – with offerings at every price point.
They are open source. So I can get in on free features and stay with Scalar no matter how big my API needs blow up.”
Eron, Documentation Engineer @ Qrvey
Docs
## The Modern Documentation Platform for Your API and Everything Else
Write documentation with Markdown and MDX, generate API references from OpenAPI and AsyncAPI, and keep everything up to date with two-way Git sync.
** Markdown and MDX **** OpenAPI + AsyncAPI **** Two-Way Git Sync **** Custom HTML/CSS/JS **** Chat with AI/MCP **** Private or Public**
[Create Docs → ](https://dashboard.scalar.com/register)[Learn More →](/products/docs)
 
Scalar SDK Generation
## One Commit To Update All Your SDKs
Bring your OpenAPI document and get type-safe client libraries for TypeScript, Python, Golang, PHP, Java and Ruby with more languages coming soon.
** OpenAPI-First **** Custom-code **** Code Samples **** OpenAPI Authentication **** Syncs with Docs **** File Streaming Support**
[Generate SDK → ](https://dashboard.scalar.com/register)[Learn More →](/products/sdk-generator)
 
MCP & Agent
## Turn Your OpenAPI Documents Into an MCP Server
Upload your OpenAPI documents and expose them as a hosted MCP server: just-in-time tool calls, secure delegated auth, and only 0.2% of your context window no matter how many APIs you connect.
** Just-in-time tool calls **** Secure delegated auth **** Scoped access **** Isolated execution **** Markdown in MCP **** Public and internal APIs**
[Get Started → ](https://dashboard.scalar.com/register)[Learn More →](/products/agent)
 
Marc from Scalar here,
There's no better feeling than building and being enabled by the software you are integrating with.
We've all experienced friction with out-of-date docs, no client SDKs in your favorite language, and no one to talk to about your struggles on-boarding.
But we've also experienced those magical APIs that just work with everything you need right there. This drives our simple three tenants at Scalar: Accessibility, Open-Source, and API First. Making on-boarding easier and magical enables people to build, and being API first means your business can scale for the future (LLMs).
Why Open-Source? If done right, it’s transparent, builds industry standards (OpenAPI), accelerates innovation, and fosters collaboration. We love Open-Source and keep it core to our values.
We are fans of “show don't tell here” at Scalar: so try our Docs (this page), our SDKs for our API that includes our API Client, Agent to chat with APIs, and our GitHub for all our open-source products. As always, we love your feedback so drop us a line in our discord, email, or book a call with me to see how we can help.
**Marc Laventure**\
CEO, Scalar
## What are you waiting for?
We're committed to enabling developers and companies to practice the highest of API industry standards.
[Get Started](https://dashboard.scalar.com/register) [Book a Demo](https://scalar.cal.com/forms/142d1e65-97d2-4d03-94c3-96f98ddef95a)
[Community →](https://discord.gg/scalar) [GitHub →](https://github.com/scalar/scalar) [Contact Us →](mailto:support@scalar.com)
 
API Docs
Write beautiful documentation with Markdown, MDX, OpenAPI, AsyncAPI, and two-way Git sync.
[Learn More](/products/docs)
 
SDKs
Bring your OpenAPI document and get type-safe client libraries for TypeScript, Python and more.
[Learn More](/products/sdk-generator)
 
API Registry
Managing & versioning OpenAPI Documents with a deep Git integration.
[Learn More](/products/registry)
 
MCP & Agent
OpenAPI-backed MCP servers and SDKs that connect your APIs to LLMs with just-in-time tools and delegated authentication.
[Learn More](/products/agent)
# API documentation platform
Scalar Docs is an API documentation platform that puts product guides and interactive API references in one developer portal, generated from the OpenAPI documents you already maintain.
Write in Markdown or MDX, pull content from GitHub, preview every pull request, and deploy on merge or from anywhere with the CLI, so your docs stay in sync with your code. All of scalar.com is fully built with Scalar Docs.
[Get Started](https://dashboard.scalar.com/register) [Book a Demo](https://scalar.cal.com/forms/142d1e65-97d2-4d03-94c3-96f98ddef95a)

## Why API teams choose Scalar Docs
* **Trusted by teams you know.** Bobcat, Thomson Reuters, Clerk, Lufthansa, PAR, Zoom, Tailscale, and Later publish developer documentation with Scalar Docs. PAR moved its public developer portal to Scalar in 2025; [read the PAR story](/customers/partech).
* **Built on an open-source reference with 15.7k GitHub stars.** Every API page is rendered by the MIT-licensed [Scalar API Reference](/products/api-references), which Microsoft Learn documents in [Use Scalar for interactive API documentation](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/openapi/using-openapi-documents#use-scalar-for-interactive-api-documentation).
* **The default docs UI in eight frameworks.** Effect, ElysiaJS, HappyX, Litestar, Nitro, oRPC, Platformatic, and Spry ship the Scalar reference out of the box, so many of your developers have used it before they reach your portal.
## Guides and API references in one site
Most teams end up with two sites: a reference generated from OpenAPI and a separate guides site that drifts out of date. Scalar Docs puts both under one navigation, one search, and one domain. Add one API or hundreds, each with its own interactive reference and a Test Request button that opens the [API client](/products/api-client) in place. [Versions](/products/docs/configuration/versions) keep older releases readable next to the current one.
## Docs as code, with a dashboard when you want one
Content lives in your repository as Markdown and MDX, configured by a single [`scalar.config.json`](/products/docs/configuration/scalar.config.json). Git Sync publishes on merge, [preview deployments](/products/docs/deployment/preview-deployments) put a link on every pull request, and the [CLI](/products/docs/deployment/cli) deploys from any CI.
## Ready for AI readers
Every published site serves [`/llms.txt` and `/llms-full.txt`](/products/docs/configuration/llms-txt) automatically, [Ask AI](/products/docs/configuration/ask-ai) answers questions from your content, and a Docs MCP endpoint lets AI clients search and read your docs. The same OpenAPI document can also power [SDKs](/products/sdk-generator) and [hosted MCP servers](/products/agent/mcp).
## Start from your framework
If your API is not documented yet, begin with the framework you already use: [.NET](/docs-for/dotnet), [FastAPI](/docs-for/fastapi), [NestJS](/docs-for/nestjs), or [Hono](/docs-for/hono). New to OpenAPI? The [learn hub](/learn) covers the basics.
[Start a free 7-day trial](https://dashboard.scalar.com/register) and publish to a hosted subdomain, or [book a demo](https://scalar.cal.com/forms/142d1e65-97d2-4d03-94c3-96f98ddef95a) to plan a migration.
## Your documentation, always up to date
** Markdown & MDX**
** Custom HTML/CSS/JS**
** Fast CDN**
** Multiple API references**
** Custom themes & layouts**
** Custom domains**
** Fine-grained access**
** Sync with GitHub**
** Ask AI**
** CI/CD integration**
## The modern API documentation
Include interactive API references for a single API or hundreds of APIs. Everything is based on the OpenAPI standard, so your documentation can stay in sync with the API document your team already maintains.
Just need an API reference? Use the [API Reference](/products/api-references/getting-started). It is open source, free, and has integrations for REST API frameworks.
Ready to build? Follow the [Getting Started guide](/products/docs/getting-started) to publish your first documentation site in minutes.
## Plans
| Feature | Free | Pro | Enterprise |
| ---------------------------------------------------------------------------- | ---- | -------- | ---------- |
| Subdomains, API references, themes, email domain access | - | Included | Included |
| Custom domains, guides, versions, Git Sync, Markdown, MDX, and landing pages | - | Included | Included |
| SSO/SAML, RBAC, priority support, and dedicated Slack or Teams support | - | - | Included |
Publishing a Docs site needs a paid plan. Every new team starts with a 7-day trial that includes Docs publishing.
[See the full comparison](/pricing) for Docs and the other Scalar products.
## Ready to publish?
We are committed to enabling developers and companies to practice the highest API industry standards.
[Get started](https://dashboard.scalar.com/register) [Book a demo](https://scalar.cal.com/forms/142d1e65-97d2-4d03-94c3-96f98ddef95a)
## Frequently asked questions
**What is an API documentation platform?**
It is a tool that publishes everything a developer needs to use your API in one place: an interactive reference generated from your OpenAPI document, written guides, search, and access control. Scalar Docs does this with Markdown or MDX content stored in Git.
**Is there a free plan?**
Every new team starts with a free 7-day trial that includes Docs publishing. After the trial, publishing a Docs site needs a paid plan, starting with Pro at $150 per month, which adds custom domains, Git Sync, Markdown, and MDX. See [pricing](/pricing) for every plan.
**Can I host my docs on my own domain?**
Yes. Custom domains are included from the Pro plan, and subpath hosting is available on Business. See [domains](/products/docs/configuration/domains).
**Do my docs stay in sync with my OpenAPI document?**
Yes. API references are generated from your OpenAPI or AsyncAPI documents, so publishing a new version of the document updates the reference. With Git Sync, a merge to your branch republishes the site.
**Can I keep some documentation private?**
Yes. Access groups, included from the Pro plan, limit who can read your guides and API references. See [private docs](/products/docs/configuration/private-docs).
**How do I migrate from another documentation tool?**
Most migrations come down to moving Markdown files and pointing Scalar at your OpenAPI document. We have guides for [Swagger UI](/resources/migration/swagger-ui), [Stoplight](/resources/migration/stoplight), and [Bump.sh](/resources/migration/bump), and Enterprise plans include migration services.
## Related
* **Learn:** [What is OpenAPI?](/learn/openapi/what-is-openapi) · [OpenAPI vs Swagger](/learn/openapi/openapi-vs-swagger)
* **Docs:** [Getting started with Scalar Docs](/products/docs/getting-started)
* **Product:** [API Reference](/products/api-references) — the open-source renderer behind every Scalar Docs API page
# Getting Started
Create and publish your first documentation site with Scalar Docs in minutes. Write guides in Markdown or MDX, add API documents for interactive API references, and deploy from GitHub, the CLI, or the web editor.
## Create docs in three steps
Create a Docs project from the dashboard, the [Starter Kit](starter-kit.md), or any folder that contains a `scalar.config.json` file.
```bash
npx @scalar/cli project preview
```
Write guides in Markdown or MDX, then add API documents for interactive API references.
```json
{
"scalar": "2.0.0",
"navigation": {
"routes": {
"/getting-started": {
"type": "page",
"filepath": "docs/getting-started.md"
}
}
}
}
```
Use preview deployments for review, publish from the CLI, or connect GitHub Actions for automatic deployments.
```bash
npx @scalar/cli project publish --slug your-docs
```
## Write anywhere
| Source | Description |
| ------ | ----------- |
| **GitHub** | Keep content and API documents in your repository. Use [preview deployments](deployment/preview-deployments.md), [automatic deployment](deployment/automatic-deployment.md), [GitHub Actions](deployment/github-actions.md), and [scalar.config.json](configuration/scalar.config.json.md). |
| **Any folder or CLI** | Work from any folder or repository without granting repository access. Publish with [`npx @scalar/cli project publish --slug your-docs`](deployment/cli.md). |
| **Web editor** | Edit and store docs at [docs.scalar.com](https://docs.scalar.com). No Git required. |
## Next steps
- Scaffold a project with the [Starter Kit](starter-kit.md)
- Configure your site with [scalar.config.json](configuration/scalar.config.json.md)
- Structure your sidebar with [Navigation](configuration/navigation.md)
- Deploy automatically with [GitHub Actions](deployment/github-actions.md)
Just need an API reference? Use the [API Reference](../../guides/api-references/getting-started.md). It is open source, free, and has integrations for REST API frameworks.
# Privacy
## No third-party tracking
Docs is privacy-friendly by default:
- We do not inject third-party analytics or tracking scripts into your pages.
- We do not set tracking cookies.
- We do not track readers across sites or build visitor profiles.
That said, you are free to [add any HTML/JS](./content/html-css-js.md) to your projects.
## First-party page view analytics
Scalar records page views on its own servers when it serves a page, so you can see how your documentation is used. Nothing is added to your pages, and no cookies are set for analytics.
Each page view records:
- the page path, domain, response status, and content type
- the referrer
- the browser or client family, for example Chrome or Cursor, not the full user agent
- whether the visitor is a person, a bot, an LLM crawler, or an MCP client
- a visitor ID
For people, the visitor ID is a pseudonym derived from a keyed hash of the IP address and user agent. It changes every day, so a visitor cannot be followed from one day to the next. The IP address itself is never stored. Bots, LLM crawlers, and MCP clients are counted as groups, not as individuals.
Only successfully served pages count. Failed requests and other files, like images and scripts, are not recorded.
You can view your analytics in the editor under **Settings → Analytics**.
### Turn off analytics
Open **Settings → Analytics** and turn off **Enable analytics**. The change applies from your next publish. You need permission to edit the project.
## Technically required cookies only
We use a small set of technically required cookies for authentication and the routing functionality:
- always: `scalar-docs-subpaths` lists the projects that share your domain, so search works across them
- if authenticated: `scalar-registry-auth` contains your authentication token (HTTP Only, not accessible through JS)
- while signing in to a private site: `scalar-docs-verifier` holds a one-time sign-in code. It is HTTP Only, sent only to the sign-in callback, and expires after an hour.
## Content Signals
Content Signals declare how search and AI crawlers may use your published documentation. Scalar adds a `Content-Signal` line to the generated `robots.txt`. By default, search indexing, AI input, and AI training are all allowed.
Open your documentation project's **Settings → Content Signals** to change these preferences:
- **Search**: building a search index and showing links and short excerpts.
- **AI input**: using content as input for AI answers, including retrieval and grounding.
- **AI training**: training or fine-tuning AI models.
Turn an individual signal off to declare `no` for that use. Turn **Enable** off to omit the entire `Content-Signal` line; this does not declare `no` for all uses. Publish your changes to update the generated `robots.txt`.
These preferences are advisory and depend on crawlers honoring them. They do not restrict access to your documentation or change its authentication settings.
You can also set these preferences in [`siteConfig.contentSignals`](./configuration/site-config.md#content-signals). If your project's assets include a custom `robots.txt`, Scalar preserves that file; update its Content Signals directly.
# Docs Starter Kit
The [Docs Starter Kit](https://github.com/scalar/starter) is a ready-to-use template for building beautiful documentation with Markdown and OpenAPI. Fork or clone the repository and make it your own — everything in the template is meant to be modified, extended, or replaced to fit your project.
## Project structure
The starter includes a minimal layout: a `docs/` folder (with `api-reference/` for API documents and `content/` for free-form content) and a `scalar.config.json` file at the repository root.
## 1. Preview your docs
Run a local development server to see your changes in real-time:
```bash
npx @scalar/cli project preview
```
This starts a live preview at `http://localhost:7970` where every edit you make is instantly visible.
Read more about [Preview deployments](deployment/preview-deployments.md) and the [CLI](deployment/cli.md).
## 2. Include API documents
Drop your API documents into `docs/api-reference/`, and add them to `scalar.config.json` to have them automatically become interactive API references.
The starter kit includes an example OpenAPI document to show you how it works.
Read more about [scalar.config.json](configuration/scalar.config.json.md) and [Getting started](getting-started.md) with Docs.
## 3. Customize everything
Make it yours with themes, custom CSS, and MDX. Configure your documentation structure, navigation, and styling through [scalar.config.json](configuration/scalar.config.json.md).
For appearance options, see [Themes](configuration/themes.md).
## 4. Publish your docs
First, authenticate with your Scalar account:
```bash
npx @scalar/cli auth login
```
Create a project to publish to. You only need to do this once:
```bash
npx @scalar/cli project create --name "My Docs" --slug my-docs
```
If that slug is already taken, Scalar picks a unique one and prints it. Use the printed slug in the next step.
Then publish your documentation to that project:
```bash
npx @scalar/cli project publish --slug my-docs
```
Your site will be available at `.apidocumentation.com`. The subdomain is `siteConfig.subdomain` from your `scalar.config.json`, or your project slug if that is not set. The CLI prints the URL when the publish finishes.
## Stuck?
Check whether your `scalar.config.json` is valid:
```bash
npx @scalar/cli project check-config
```
For full options, see the [Configuration reference](configuration/scalar.config.json.md).
We are here to help:
- [Email support@scalar.com](mailto:support@scalar.com)
- [Chat with us on Discord](https://discord.gg/scalar)
- [Schedule a call](https://scalar.cal.com/forms/142d1e65-97d2-4d03-94c3-96f98ddef95a)
# Agent Skills
You can install a reusable Scalar Docs skill for coding agents with the [`skills`](https://www.npmjs.com/package/skills) CLI.
## Install the Scalar Docs skill
Install directly from GitHub:
```bash
npx skills add scalar/scalar --skill scalar-docs
```
## Install to specific agents
Example for Cursor and Codex:
```bash
npx skills add scalar/scalar \
--skill scalar-docs \
--agent cursor \
--agent codex
```
## Install globally
To make the skill available across projects:
```bash
npx skills add scalar/scalar --skill scalar-docs --global
```
## MCP: Scalar Documentation
Use `https://scalar.com/mcp` to add Scalar Documentation as an MCP server in your agent tooling.
# scalar.config.json
The `scalar.config.json` file is the central configuration file for Docs. It defines your project's metadata, navigation structure, site settings, and deployment options.
## Creating the configuration file
You can create a configuration file manually or use the Scalar CLI:
```bash
npx @scalar/cli project init
```
This command creates a `scalar.config.json` file in your current directory with a basic structure to get you started.
## Basic structure
Here is a minimal configuration to get started:
```json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"info": {
"title": "My Documentation",
"description": "The best documentation you've read today"
},
"navigation": {
"routes": {
"/": {
"title": "Introduction",
"type": "page",
"filepath": "docs/introduction.md"
}
}
}
}
```
## Autocomplete in VS Code and Cursor
To get autocomplete and validation in your editor, enable JSON schema downloads in VS Code (or Cursor):
```json
// .vscode/settings.json
{
"json.schemaDownload.enable": true
"json.schemaDownload.trustedDomains": {
"https://registry.scalar.com/": true,
}
}
```
The `$schema` property in your configuration file tells the editor where to find the schema:
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config"
}
```
Your editor will now provide autocomplete suggestions and highlight invalid properties.
## Configuration reference
### Root properties
| Property | Type | Description |
| --------------------- | --------- | --------------------------------------------------------------------------------------------------------------- |
| `$schema` | `string` | JSON Schema URL for editor autocomplete and validation |
| `scalar` | `string` | Configuration version. Use `"2.0.0"` for the latest format |
| `info` | `object` | Project metadata (title, description) |
| `navigation` | `object` | Navigation structure (header links, routes, sidebar, tabs). See [Navigation](navigation.md) for details |
| `versions` | `object` | Multi-version navigation structure. Use instead of `navigation` for versioned docs. See [Versions](versions.md) |
| `siteConfig` | `object` | Site-level configuration (domain, theme, head, logo, access control) |
| `assetsDir` | `string` | Path to the assets directory (relative to repository root) |
| `root` | `string` | Directory that route `filepath` values resolve against, relative to the configuration file |
| `publishOnMerge` | `boolean` | Publish the site when commits land on the tracked branch. See [Publishing](#publishing) |
| `publishPreviews` | `boolean` | Build a preview deployment for every pull request. See [Publishing](#publishing) |
| `pullRequestComments` | `boolean` | Post the preview URL as a comment on each pull request. See [Publishing](#publishing) |
| `ruleset` | `object` | Default Spectral ruleset and publish policy for every OpenAPI route. See [ruleset](#ruleset) |
### info
Project metadata displayed in various places:
```json
{
"info": {
"title": "My Documentation",
"description": "Comprehensive guides for our API"
}
}
```
### siteConfig
Configure your site's domain, appearance, and custom assets:
```json
{
"siteConfig": {
"subdomain": "acme",
"customDomain": "docs.example.com",
"theme": "purple",
"logo": {
"darkMode": "https://example.com/logo-dark.svg",
"lightMode": "https://example.com/logo-light.svg"
},
"head": {
"scripts": [{ "path": "assets/analytics.js" }],
"styles": [{ "path": "assets/custom.css" }],
"meta": [{ "name": "description", "content": "My docs description" }],
"links": [{ "rel": "icon", "href": "/favicon.png" }]
},
"routing": {
"redirects": [
{ "from": "/old-path", "to": "/new-path" }
]
}
}
}
```
#### siteConfig properties
| Property | Type | Description |
| ---------------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `subdomain` | `string` | Subdomain to publish to, as in `.apidocumentation.com`. Must be unique on Scalar. See [Domains](domains.md) |
| `customDomain` | `string` | Custom domain for the site. See [Domains](domains.md) |
| `subpath` | `string` | URL subpath for multi-project deployments (e.g., `/guides`, `/api`) |
| `isPrivate` | `boolean` | Require visitors to sign in. See [Access Control](site-config.md#access-control) |
| `accessGroups` | `string[]` | Slugs of the access groups allowed to view a private site. See [Access Control](site-config.md#access-control) |
| `loginPortal` | `string` | Slug of a custom login portal for a private site. See [Access Control](site-config.md#access-control) |
| `theme` | `string` | Built-in theme name, path to a `.css` file, or one of your team's themes. See [Themes](themes.md) |
| `logo` | `object` | Logo URLs for dark and light modes |
| `head` | `object` | Custom scripts, styles, meta tags, and links |
| `routing` | `object` | URL redirects configuration |
| `colorScheme` | `object` | Light/dark mode appearance settings. See [Site](site-config.md#color-scheme) |
| `layout` | `object` | Global layout options, including search and the light/dark toggle. See [Site](site-config.md#layout) |
| `agent` | `object` | Ask AI button settings. See [Ask AI](ask-ai.md) |
| `footer` | `object` | Custom HTML footer. See [Site](site-config.md#footer) |
| `rss` | `object` or `array` | RSS feeds for changelog-style pages. See [Site](site-config.md#rss) |
| `contentSignals` | `object` or `false` | Search and AI crawler preferences for `robots.txt`. See [Site](site-config.md#content-signals) |
### Publishing
When your project is connected to a GitHub or Bitbucket repository, three root properties control when Scalar publishes. The toggles under **Settings → Git Sync** in the dashboard read and write these same properties, so a change in either place shows up in the other.
```json
{
"publishOnMerge": true,
"publishPreviews": true,
"pullRequestComments": true
}
```
| Property | Type | Default | Description |
| --------------------- | --------- | ------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `publishOnMerge` | `boolean` | `true` | Publish the live site when commits land on the tracked branch. See [Automatic Deployment](../deployment/automatic-deployment.md) |
| `publishPreviews` | `boolean` | `false` | Build a preview deployment for every pull request. See [Preview Deployments](../deployment/preview-deployments.md) |
| `pullRequestComments` | `boolean` | `false` | Post the preview URL as a comment on each pull request |
If a property is missing from the file, Scalar falls back to the setting stored on the repository connection. The tracked branch itself is set in the dashboard, not in `scalar.config.json`.
### ruleset
Lint every OpenAPI route with a [Spectral ruleset](../../registry/rules.md), and optionally block publishing when it finds problems. Point at a ruleset file in your repository, or at a ruleset in your team's registry:
```json
{
"ruleset": {
"filepath": "rules/spectral.yaml",
"blockPublishOn": "error"
}
}
```
```json
{
"ruleset": {
"namespace": "acme",
"slug": "api-guidelines",
"version": "1.2.0"
}
}
```
| Property | Type | Description |
| ---------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `filepath` | `string` | Path to a Spectral ruleset file, relative to the configuration root |
| `namespace` | `string` | Namespace of the ruleset in your team registry |
| `slug` | `string` | Slug of the ruleset in your team registry |
| `version` | `string` | Version of the ruleset in your team registry |
| `disableSync` | `boolean` | When `filepath` is set alongside registry coordinates, do not publish the file to the registry each time the docs publish |
| `blockPublishOn` | `string` | Lowest severity that blocks publishing: `error`, `warning`, `info`, `hint`, or `none`. Omit it to use the registry ruleset's policy |
An OpenAPI route can set its own `ruleset`. Its keys override the project-level ones one at a time, so a route can change `blockPublishOn` and keep the default ruleset.
### navigation
For detailed navigation configuration, see [Navigation](navigation.md).
## Full example
Here is a more complete example showing common configuration options:
```json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"info": {
"title": "Acme API Documentation",
"description": "Everything you need to integrate with Acme"
},
"assetsDir": "docs/assets",
"publishOnMerge": true,
"publishPreviews": true,
"pullRequestComments": true,
"siteConfig": {
"subdomain": "acme",
"theme": "default",
"logo": {
"darkMode": "https://example.com/logo-dark.svg",
"lightMode": "https://example.com/logo-light.svg"
},
"head": {
"meta": [
{ "name": "description", "content": "Acme API documentation and guides" }
],
"links": [
{ "rel": "icon", "href": "/favicon.png" }
]
}
},
"navigation": {
"header": [
{ "type": "link", "title": "Dashboard", "to": "https://dashboard.example.com" }
],
"routes": {
"/": {
"type": "group",
"title": "Acme",
"children": {
"": {
"type": "page",
"title": "Introduction",
"filepath": "docs/introduction.md",
"icon": "phosphor/regular/house"
},
"/api": {
"type": "openapi",
"title": "API Reference",
"url": "https://example.com/openapi.yaml",
"icon": "phosphor/regular/notebook"
}
}
}
}
}
}
```
## File location
By default, the `scalar.config.json` file should be placed in the root of your GitHub repository. If you need to place it in a different location, you can configure the path in the [Scalar Dashboard](https://dashboard.scalar.com/).
## Deploying multiple projects on the same domain
You can deploy multiple documentation projects on the same subdomain or custom domain by using the `subpath` property. Each project lives in its own repository with its own `scalar.config.json`, but they share the same domain.
For example, you might want to have:
- `docs.example.com/` — Your main documentation
- `docs.example.com/guides/` — Tutorial guides
- `docs.example.com/api/` — API reference
To set this up, create a separate repository for each project and configure them with the same `subdomain` or `customDomain` but a different `subpath`:
**Repository 1: Main documentation**
```json
// scalar.config.json
{
"siteConfig": {
"customDomain": "docs.example.com"
}
}
```
**Repository 2: Guides**
```json
// scalar.config.json
{
"siteConfig": {
"customDomain": "docs.example.com",
"subpath": "/guides"
}
}
```
**Repository 3: API reference**
```json
// scalar.config.json
{
"siteConfig": {
"customDomain": "docs.example.com",
"subpath": "/api"
}
}
```
Each repository is deployed independently, but all projects appear under the same domain with their respective subpaths.
# Site Config
The site configuration defines global settings for your documentation site: branding, custom head elements, an announcement banner, footer content, and routing rules. These settings apply across your entire documentation site.
All site settings are configured within the `siteConfig` object in your `scalar.config.json` file.
**Example**
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"siteConfig": {
"logo": "https://example.com/logo.svg",
"theme": "default"
}
}
```
## Logo
The `logo` property defines your site's logo. You can provide a single URL for all modes, or separate logos for light and dark themes.
### Where the Logo Appears
Your logo renders on the first of these surfaces your site has:
1. The **header**, if you declare `navigation.header` or set `layout.header` to `true`
2. The **tabs**, if you have `navigation.tabs` but no header
3. The **sidebar**, if you have neither
To force the logo to go in the header, set `layout.header` to `true`. If a page hides all three surfaces through its [layout options](navigation.md#layout-options), the logo does not render on that page.
If you do not set a `logo`, your project title from `info.title` renders in the same place instead.
### Single Logo
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"siteConfig": {
"logo": "https://example.com/logo.svg"
}
}
```
### Light and Dark Mode
For better visibility across themes, provide different logos for light and dark modes:
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"siteConfig": {
"logo": {
"darkMode": "https://example.com/logo-dark.svg",
"lightMode": "https://example.com/logo-light.svg"
}
}
}
```
### Properties
| Property | Type | Required | Description |
| ---------------- | -------- | -------- | --------------------------------------- |
| `logo` | `string` | No | URL to a single logo for all themes |
| `logo.darkMode` | `string` | No | URL to the logo displayed in dark mode |
| `logo.lightMode` | `string` | No | URL to the logo displayed in light mode |
## Theme
The `theme` property sets a platform-defined theme for your documentation site.
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"siteConfig": {
"theme": "purple"
}
}
```
### Properties
| Property | Type | Required | Description |
| -------- | -------- | -------- | --------------------------------- |
| `theme` | `string` | No | Slug for a platform-defined theme |
## Color Scheme
The `colorScheme` property sets the light/dark mode your site loads in. To move or hide the toggle, see [Where the Toggle Appears](#where-the-toggle-appears).
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"siteConfig": {
"colorScheme": {
"default": "system"
}
}
}
```
### Properties
| Property | Type | Default | Description |
| ------------ | -------------------------------- | ---------- | ------------------------------------------ |
| `default` | `"light" \| "dark" \| "system"` | `"system"` | Default color scheme on page load |
| `showToggle` | `boolean` | `true` | **Deprecated.** Use [`layout.colorSchemeToggle`](#where-the-toggle-appears). `false` still hides the toggle everywhere |
### Where the Toggle Appears
Set `layout.colorSchemeToggle` to `"sidebar"` (the default), `"header"`, `"tabs"`, or `false` to hide it. The sidebar shows a switch; the header and tabs show a sun/moon icon.
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"siteConfig": {
"layout": {
"colorSchemeToggle": "header"
}
}
}
```
If a page does not have that surface, the toggle falls back to the sidebar, then the header, then the tabs, and does not render if the page has none of them. On mobile, pages without a sidebar show it in the header. You can override the location per page in its [layout options](navigation.md#layout-options).
### Examples
#### Force Light Mode
Force your documentation to always display in light mode without a toggle:
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"siteConfig": {
"colorScheme": {
"default": "light"
},
"layout": {
"colorSchemeToggle": false
}
}
}
```
#### Force Dark Mode
Force your documentation to always display in dark mode without a toggle:
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"siteConfig": {
"colorScheme": {
"default": "dark"
},
"layout": {
"colorSchemeToggle": false
}
}
}
```
#### System Preference with Toggle
Respect the user's system preference while allowing them to override it:
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"siteConfig": {
"colorScheme": {
"default": "system"
}
}
}
```
## Social Cards
The `og` property points at your own template for the social card shown when a page is shared. Without it, Scalar draws a card from your theme, logo and page title.
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"siteConfig": {
"og": {
"imageTemplate": "./og/card.tsx"
}
}
}
```
### Properties
| Property | Type | Required | Description |
| --------------- | -------- | -------- | --------------------------------------------------------------------------------- |
| `imageTemplate` | `string` | No | Path to a TSX or JSX template, relative to `scalar.config.json` and inside the project |
See [Social Cards](social-cards.md) for how to write one.
## Ask AI
The `agent` property controls the appearance of [Ask AI](ask-ai.md) on your documentation site: the Ask AI button, its placement in the sidebar, the position of the floating chat widget, and the suggested questions shown in the chat.
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"siteConfig": {
"agent": {
"position": "right",
"suggestions": ["How do I authenticate?", "What are the rate limits?"]
}
}
}
```
### Properties
| Property | Type | Default | Description |
| ----------------- | ----------------------------- | ---------- | ------------------------------------------------------------------------------------------------------------- |
| `enabled` | `boolean` | — | Whether the Ask AI button is shown on the site |
| `buttonText` | `string` | `"Ask AI"` | Label shown on the Ask AI button |
| `sidebarPosition` | `"below-search" \| "default"` | — | Placement of the Ask AI button in the sidebar. `"default"` renders it next to the search bar; `"below-search"` renders it on its own row beneath the search bar |
| `position` | `"center" \| "right"` | `"center"` | Where the floating chat widget anchors at the bottom of the viewport |
| `suggestions` | `string[]` | — | Suggested questions shown as pills above the chat input when it is focused. Two or three short questions work best |
| `mcp` | `object` | — | References an MCP server and installation by slug (`serverSlug`, `installationSlug`), resolved on publish |
## Layout
The `layout` property controls global layout options that apply to all pages unless overridden by a page's own [layout options](navigation.md#layout-options).
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"siteConfig": {
"layout": {
"toc": true,
"header": true,
"pageTitle": true,
"pageActions": true,
"pageNav": true,
"lastUpdated": false,
"feedback": false,
"search": {
"enabled": true,
"position": "header"
}
}
}
}
```
### Properties
| Property | Type | Default | Description |
| ------------- | --------- | -------- | ---------------------------------------------- |
| `toc` | `boolean` | `true` | Whether to show the table of contents globally |
| `header` | `boolean` | — | Whether to show the header globally. Falls back to whether or not [`navigation.header`](navigation.md#header) is declared |
| `pageTitle` | `boolean` | `true` | Whether to show page titles globally |
| `pageActions` | `boolean` | `true` | Whether to show page actions globally |
| `pageNav` | `boolean` | `true` | Whether to show previous and next page links at the bottom of each page |
| `lastUpdated` | `boolean` | `false` | Whether to show the date each page last changed, above the previous and next links. See [Last updated date](#last-updated-date) |
| `feedback` | `boolean` | `false` | Whether to ask readers if each page was helpful, between the last updated date and the previous and next links. See [Page feedback](#page-feedback) |
| `search` | `object` | — | Search bar configuration |
| `colorSchemeToggle` | `"sidebar" \| "header" \| "tabs" \| false` | `"sidebar"` | Where to show the light/dark toggle. See [Where the Toggle Appears](#where-the-toggle-appears) |
### Last updated date
Scalar records the date for you, so there is no field to set it by hand. Each time you publish, Scalar compares every page's content with the previous publish, and the date moves forward only for pages whose content changed. Your first publish dates every page to that day.
Previews do not have a publish history, so they show the current date.
### Page feedback
Page feedback is off unless you turn it on, because it puts a question at the foot of every page it covers. Readers answer with a thumbs up or down, then can pick a reason from a short list.
Set `feedback` here to ask on every page, or on a single page with its own [layout options](navigation.md#layout-options). A page's own value wins in either direction, so you can turn it on site-wide and off for one page, or the other way around.
Votes appear in the editor under **Settings → Analytics**, in a **Page feedback** panel that shows once `feedback` is on for any page. The widget never appears in a preview, or while [analytics is turned off](../privacy.md#turn-off-analytics) for the project, since there is nowhere to record the vote.
### Search Configuration
The `search` object within `layout` controls the global search behavior.
Search finds guide content and API content, including parameter names, request and response fields, models, webhooks, and AsyncAPI content. You do not need to enable Ask AI to search these fields. Exact names rank above incidental mentions in descriptions, and results link to their API reference destinations.
Models appear after you type a query. They are excluded from the initial suggestions so guide pages and API overviews remain easy to find. The search index is generated during the site build; publish a new build to index updated API content.
| Property | Type | Default | Description |
| ---------- | --------------------------- | ---------- | ------------------------------------- |
| `enabled` | `boolean` | `true` | Enable or disable search globally |
| `position` | `"header" \| "sidebar"` | `"header"` | Where to display the search bar |
#### Disable Search
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"siteConfig": {
"layout": {
"search": {
"enabled": false
}
}
}
}
```
#### Move Search to Sidebar
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"siteConfig": {
"layout": {
"search": {
"position": "sidebar"
}
}
}
}
```
## Head
The `head` property allows you to inject custom elements into the HTML `` of your documentation pages. This is useful for adding custom styles, scripts, meta tags, and favicon links.
An `og:image` set here applies to every page and replaces the [social card](social-cards.md) Scalar generates, including one from your own template.
### Example
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"siteConfig": {
"head": {
"title": "My Documentation",
"meta": [
{
"name": "description",
"content": "Documentation for my API"
},
{
"property": "og:image",
"content": "https://example.com/og-image.png"
}
],
"styles": [
{
"path": "assets/custom-styles.css"
}
],
"scripts": [
{
"path": "assets/analytics.js"
}
],
"links": [
{
"rel": "icon",
"href": "/favicon.png"
}
]
}
}
}
```
### Properties
| Property | Type | Required | Description |
| --------- | ----------------- | -------- | -------------------------------------- |
| `title` | `string` | No | The page title |
| `meta` | `array \| object` | No | Meta tags for SEO and social sharing |
| `styles` | `array` | No | CSS files to include |
| `scripts` | `array` | No | JavaScript files to include |
| `links` | `array` | No | Link elements (favicon, preload, etc.) |
### Meta Tags
Meta tags can be provided as an array of objects or as a key-value object:
**Array Format**
```json
"meta": [
{
"name": "description",
"content": "My API documentation"
},
{
"property": "og:title",
"content": "My API"
}
]
```
**Object Format**
```json
"meta": {
"description": "My API documentation",
"og:title": "My API"
}
```
### Styles
Include custom CSS files in your documentation. Each entry loads from either a local `path` or a remote `url`:
```json
"styles": [
{
"path": "assets/custom-styles.css",
"tagPosition": "head"
},
{
"url": "https://example.com/theme.css"
}
]
```
| Property | Type | Required | Description |
| ------------- | --------------------------------------- | -------- | -------------------------------------------- |
| `path` | `string` | Yes\* | Relative path to the CSS file |
| `url` | `string` | Yes\* | Remote URL to the CSS file |
| `tagPosition` | `"head" \| "bodyOpen" \| "bodyClose"` | No | Where to inject the style tag |
\* Provide either `path` or `url`.
### Scripts
Include custom JavaScript files. Each entry loads from either a local `path` or a remote `url`:
```json
"scripts": [
{
"path": "assets/analytics.js",
"tagPosition": "bodyClose"
}
]
```
| Property | Type | Required | Description |
| ------------- | --------------------------------------- | -------- | --------------------------------------------------------------------------------- |
| `path` | `string` | Yes\* | Relative path to the JavaScript file |
| `url` | `string` | Yes\* | Remote URL to the JavaScript file |
| `tagPosition` | `"head" \| "bodyOpen" \| "bodyClose"` | No | Where to inject the script tag |
| `async` | `boolean` | No | Load the script without blocking the parser, running it as soon as it arrives |
| `defer` | `boolean` | No | Load the script without blocking the parser, running it after parsing in document order |
| `type` | `string` | No | The script type attribute, for example `"module"` |
\* Provide either `path` or `url`.
By default a configured script loads synchronously in the `` and blocks first render until it has downloaded and run. Set `async` or `defer` so non-critical scripts (analytics, consent banners, chat widgets) load without blocking:
```json
"scripts": [
{ "path": "assets/analytics.js" },
{ "url": "https://example.com/widget.js", "defer": true }
]
```
### Links
Add link elements for favicons, preloading resources, or other purposes:
```json
"links": [
{
"rel": "icon",
"type": "image/png",
"href": "/favicon.png"
},
{
"rel": "preconnect",
"href": "https://fonts.googleapis.com"
}
]
```
| Property | Type | Description |
| -------- | -------- | ------------------------------------- |
| `rel` | `string` | The relationship type (icon, preload) |
| `href` | `string` | The URL or path to the resource |
| `type` | `string` | The MIME type of the resource |
## Banner
The `banner` property shows an announcement above the header on every page, such as a launch or a scheduled maintenance.
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"siteConfig": {
"banner": {
"content": "Version 2 is here. [See what changed](pages/changelog.md)",
"type": "info",
"dismissible": true
}
}
}
```
### Properties
| Property | Type | Default | Description |
| ------------- | ------------------------------------------------ | -------- | ----------------------------------------------------------------------------------------------------------- |
| `content` | `string` | — | Banner text as inline Markdown (bold, italic, code, links). An empty string hides the banner |
| `type` | `"neutral" \| "info" \| "warning" \| "critical"` | `"info"` | Color of the banner |
| `dismissible` | `boolean` | `false` | Show a close button. A dismissed banner reappears when `content` changes |
| `icon` | `string \| false` | — | An [icon key or URL](../components/icons.mdx). Defaults to an icon for the `type`; `false` hides it |
Link to your own pages by their file path, relative to the project root, as you would inside a page. Links to other sites open in a new tab.
### Styling
To change the colors, set these variables in your [theme](themes.md):
```css
:root {
--scalar-banner-background: #6e56cf;
--scalar-banner-color: #ffffff;
--scalar-banner-icon-color: #ffffff;
--scalar-banner-border-color: transparent;
}
```
To style one type, target `.scalar-banner[data-type="warning"]`.
## Footer
The `footer` property allows you to add a custom footer to your documentation site.
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"siteConfig": {
"footer": {
"filepath": "docs/footer.html"
}
}
}
```
### Properties
| Property | Type | Description |
| ---------- | -------- | ------------------------------------------ |
| `filepath` | `string` | Relative path to a custom HTML footer file |
## RSS
The `rss` property publishes an RSS feed for your changelog, so readers can subscribe to your releases in a feed reader.
Point `path` at the route your changelog lives on. The feed is written to `rss.xml` under that route — a changelog at `/changelog` publishes its feed at `/changelog/rss.xml`.
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"siteConfig": {
"rss": {
"path": "/changelog",
"title": "Scalar Changelog",
"description": "Every Scalar release, as a feed"
}
}
}
```
### Properties
| Property | Type | Required | Description |
| ------------- | -------- | -------- | ----------------------------------------------------------------------------------- |
| `path` | `string` | Yes | Route of your changelog, for example `/changelog`. Must be a plain site route with no `..` segments |
| `title` | `string` | No | Title of the feed, shown in feed readers. Defaults to your site title plus `Changelog` |
| `description` | `string` | No | Description of the feed, shown in feed readers |
| `entries` | `string` | No | How items are found. `headings` (default) turns each dated heading into an item; `pages` turns each page under `path` with a `date` in its frontmatter into an item |
### Multiple Feeds
To publish more than one feed, set `rss` to a list. Each entry is a feed with its own `path`, and each is written to `rss.xml` under that path — so `/changelog` and `/blog` publish `/changelog/rss.xml` and `/blog/rss.xml` side by side:
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"siteConfig": {
"rss": [
{
"path": "/changelog",
"title": "Scalar Changelog",
"description": "Every Scalar release, as a feed"
},
{
"path": "/blog",
"title": "Scalar Blog"
}
]
}
}
```
Every feed takes the same properties as a single one, and each path must be unique. A single feed still works exactly as shown above — the list is only needed when you want more than one.
When a page sits under more than one feed, its header shows a subscribe button for each, with the nearest feed first.
### Writing Entries
Each entry in the feed comes from a heading that carries a date in `YYYY-MM-DD` form:
```markdown
## 1.2.0 (2026-07-24)
Added a dark mode toggle to the header.
## 1.1.0 (2026-07-10)
Introduced page actions: copy as Markdown, open in editor, and report an issue.
```
The heading becomes the item title, and the content below it becomes the item description. Only the top-most heading level that carries dates starts entries; any deeper heading folds into the release above it — even one that happens to contain a date — so you can nest subheadings like `### Fixes` inside a release without splitting it apart.
If a heading looks dated but the date is not real (`## 2.0.0 (2026-13-01)`), that release is left out of the feed and the build warns you, since a typo is the only way to get there.
### Multiple Products
A changelog split across several pages works too. Every page at `path` or beneath it contributes its entries, and the feed merges them newest-first:
```
/changelog <- index page, lists the products
/changelog/api-client <- entries
/changelog/api-reference <- entries
```
An index page with no dated headings contributes nothing of its own, which is what you want when it only links to the products.
Hidden pages are skipped. A page kept out of the sidebar and the sitemap stays out of the feed as well.
### One Item per Page
For a blog, where each post is its own page rather than a heading on a shared page, set `entries` to `pages`:
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"siteConfig": {
"rss": {
"path": "/blog",
"title": "Scalar Blog",
"entries": "pages"
}
}
}
```
Now every page under `path` that carries a `date` in its frontmatter becomes one feed item, newest first:
```markdown
---
date: 2026-07-24
---
# Our new dark mode
A short introduction to the post.
```
The page title becomes the item title, its description becomes the item description, and the frontmatter `date` sets the publish date. Pages without a `date` — an index page, a draft — are left out, so nothing is syndicated by accident.
### Discovery
Every page on your site advertises the feed in its ``, so feed readers and browser extensions can find it from any URL:
```html
```
Pages at `path` and beneath it also show a subscribe button in the page header, next to Copy Page — one per feed the page belongs to.
## Access Control
Set `isPrivate` to require visitors to sign in before they can view your documentation. Members of your workspace always have access. To let anyone else in, list the [access groups](private-docs.md) allowed to view the site.
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"siteConfig": {
"isPrivate": true,
"accessGroups": ["partners", "internal-team"],
"loginPortal": "acme-portal"
}
}
```
### Properties
| Property | Type | Default | Description |
| -------------- | ---------- | ------- | ----------- |
| `isPrivate` | `boolean` | `false` | Require visitors to sign in. |
| `accessGroups` | `string[]` | — | Slugs of the access groups allowed to view the site when `isPrivate` is `true`. Up to 50. |
| `loginPortal` | `string` | — | Slug of a custom login portal. Without one, visitors sign in on the default page. |
Access groups and login portals are created in the [Scalar Dashboard](https://dashboard.scalar.com), and the config refers to them by slug. You can also manage these settings in your documentation project's **Settings → Privacy**, which reads and writes the same properties.
## Personalization
Set `userInfoHook` to your HTTPS endpoint to personalize published documentation for signed-in visitors:
```json
{
"siteConfig": {
"userInfoHook": "https://api.example.com/docs/user-info"
}
}
```
Publish the configuration, then generate the project's signing secret in **Settings → Personalization**. Your endpoint verifies Scalar's signed request and returns visitor groups, content values, and optional API playground inputs. See [Personalization](personalization.md) for the complete hook contract and a working example.
Personalization changes visibility. Use [Access Control](#access-control) to restrict access to the site.
## Content Signals
The `contentSignals` property declares how search and AI crawlers may use your published documentation. Scalar writes these preferences as a `Content-Signal` line in the generated `robots.txt`.
Content Signals are enabled by default. If you omit `contentSignals`, or omit an individual signal, all unspecified signals default to `"yes"`:
```text
Content-Signal: search=yes, ai-input=yes, ai-train=yes
```
### Properties
Set `contentSignals` to `false` to omit the directive, or use an object with these optional properties:
| Property | Type | Default | Description |
| --------- | ----------------- | ------- | ----------- |
| `enabled` | `boolean` | `true` | Whether to emit the directive. Set to `false` to retain your preferences without publishing them. |
| `search` | `"yes"` or `"no"` | `"yes"` | Building a search index and showing links and short excerpts. |
| `aiInput` | `"yes"` or `"no"` | `"yes"` | Using content as input for AI answers, including retrieval and grounding. |
| `aiTrain` | `"yes"` or `"no"` | `"yes"` | Training or fine-tuning AI models. |
### Allow Search and AI Answers, Decline AI Training
Add the following to your `scalar.config.json`:
```json
{
"siteConfig": {
"contentSignals": {
"search": "yes",
"aiInput": "yes",
"aiTrain": "no"
}
}
}
```
After publishing, the generated `robots.txt` includes:
```text
User-agent: *
Content-Signal: search=yes, ai-input=yes, ai-train=no
Allow: /
```
### Disable the Directive
Set `contentSignals` to `false` to omit the `Content-Signal` line entirely:
```json
{
"siteConfig": {
"contentSignals": false
}
}
```
Alternatively, set `contentSignals.enabled` to `false` to keep your per-signal preferences for later. Disabling the directive does not declare `no` for any use. To decline a use explicitly, keep Content Signals enabled and set that signal to `"no"`.
You can also manage these settings in your documentation project's **Settings → Content Signals**. Publish changes to update the generated file. If your project's assets include a custom `robots.txt`, Scalar preserves that file instead of generating one; edit its Content Signals directly.
Content Signals are advisory preferences that crawlers may honor. They do not block access or replace authentication. See [Privacy](../privacy.md#content-signals) for more context.
## Routing
The `routing` property configures URL redirects and path patterns for your documentation.
### Redirects
Set up redirects to handle URL changes or aliases:
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"siteConfig": {
"routing": {
"redirects": [
{
"from": "/old-path",
"to": "/new-path"
},
{
"from": "/docs/v1",
"to": "/docs/latest"
}
]
}
}
}
```
### Properties
| Property | Type | Description |
| ---------------------- | -------- | ----------------------------------- |
| `redirects` | `array` | Array of redirect rules |
| `guidePathPattern` | `string` | URL pattern for guide pages |
| `referencePathPattern` | `string` | URL pattern for API reference pages |
### Redirect Object
| Property | Type | Required | Description |
| -------- | -------- | -------- | ------------------------ |
| `from` | `string` | Yes | The source path to match |
| `to` | `string` | Yes | The destination path |
### Path Patterns
Customize the URL structure for guides and API references:
```json
"routing": {
"guidePathPattern": "/docs/:slug",
"referencePathPattern": "/api/:slug"
}
```
# Domains
Configure your documentation site's domain using either a free subdomain on `apidocumentation.com` or a custom domain. Both options are configured in the `siteConfig` object of your `scalar.config.json` file.
## Subdomain
The `subdomain` property publishes your site at `https://.apidocumentation.com`, at no extra cost. Publishing a Docs site needs a paid plan or an active trial.
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"siteConfig": {
"subdomain": "your-docs"
}
}
```
Your documentation will be available at `https://your-docs.apidocumentation.com` after deployment.
## Custom Domain
The `customDomain` property allows you to use your own domain name. This feature requires [Scalar Pro](../../pricing.md). HTTPS is enabled automatically.
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"siteConfig": {
"customDomain": "docs.example.com"
}
}
```
### DNS Configuration
Add a CNAME record at your domain provider (Namecheap, GoDaddy, Cloudflare, etc.) pointing to Scalar's DNS:
| Type | Host | Value |
| ------- | -------------------------------------------- | ---------------- |
| `CNAME` | `docs` (if the domain is `docs.example.com`) | `dns.scalar.com` |
The CNAME must be DNS-only (unproxied). If you use Cloudflare or a similar provider, disable the proxy (grey cloud) so the record resolves directly to Scalar. Proxying is not supported because Scalar performs load balancing, TLS termination (HTTP-01 / TLS-ALPN-01), and proxying for your docs. You cannot place your own CDN or WAF in front of the custom domain. Traffic must go directly to Scalar's infrastructure.
For a root domain (e.g., `example.com`), use an ALIAS or ANAME record if supported by your DNS provider, or contact support for assistance.
### TLS and certificates
SSL certificates are auto-provisioned by Let's Encrypt. Issuance is triggered the first time a GET request is made to your domain through Scalar's proxy. If you use CAA records, ensure they allow Let's Encrypt (see [Let's Encrypt CAA documentation](https://letsencrypt.org/docs/caa/) for details).
### Domain ownership
The first project that publishes with a custom domain and has the CNAME pointing to Scalar reserves that domain. No other user can use it. There is no TXT or other verification step. Ownership is established by publishing with the custom domain and having the CNAME in place.
### Edge security
[Google Cloud Armor](https://cloud.google.com/security/products/armor) policies are enabled on the load balancer for requests to custom-domain docs. These are volumetric, IP-based rules.
## Properties
| Property | Type | Required | Description |
| -------------- | -------- | -------- | ------------------------------------------------------------ |
| `subdomain` | `string` | No | Subdomain for `*.apidocumentation.com` |
| `customDomain` | `string` | No | Custom domain name (requires [Scalar Pro](../../pricing.md)) |
# Navigation
The navigation configuration defines the structure and content of your documentation sidebar. You can organize your content using pages, API references, groups, and external links to create a clear and intuitive navigation experience for your users.
All navigation is configured within the `navigation.routes` object in your `scalar.config.json` file. Each route is defined by its URL path as the key and a configuration object as the value.
**Example**
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"navigation": {
"routes": {
"/": {
"title": "Introduction",
"type": "page",
"filepath": "docs/introduction.md"
}
}
}
}
```
## Header
The `navigation.header` array defines the items that appear in the top navigation bar of your documentation site. These are typically used for authentication links, external resources, or call-to-action buttons.
The header renders whenever you declare `navigation.header`, and it is where your [logo](site-config.md#logo) appears. To override that, set `header` in your [site layout options](site-config.md#layout), `true` to always show the header or `false` to always hide it. You can also override the header visibility per page in its [layout options](#layout-options).
### Example
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"navigation": {
"header": [
{
"type": "link",
"title": "Home",
"to": "/"
},
{
"type": "link",
"title": "Log in",
"align": "end",
"to": "https://dashboard.scalar.com/login"
},
{
"type": "link",
"title": "Register",
"style": "button",
"icon": "phosphor/regular/user-plus",
"align": "end",
"newTab": true,
"to": "https://dashboard.scalar.com/register"
}
],
"routes": {
// ...
}
}
}
```
### Alignment
The header lays out in three regions, and each item picks its region with `align`:
| Value | Where the item sits |
| ----------------- | -------------------------------------------------- |
| `start` (Default) | Next to your logo |
| `center` | In the middle of the header next to the search bar |
| `end` | At the far end of the header opposite your logo |
Alignment is a property of top-level items. Items nested inside a [group](#group-dropdowns) ignore the `align` property.
### Item types
The header supports three types of item.
#### Header links
A link to a page on your site or to an external URL.
```json
{
"type": "link",
"title": "Log in",
"align": "end",
"to": "https://dashboard.scalar.com/login"
}
```
| Property | Type | Required | Description |
| -------- | ------------------------------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type` | `"link"` | Yes | Must be `"link"` |
| `groups` | `string[]` | No | Show the entry to visitors with a matching group. See [Personalization](personalization.md#filter-navigation). |
| `title` | `string` | Yes | The display text for the header link |
| `to` | `string` | Yes | The route path or URL the link points to |
| `align` | `"start" \| "center" \| "end"` | No | Which region the link sits in (defaults to `"start"`) |
| `style` | `"text" \| "button"` | No | Display style (defaults to `"text"`) |
| `icon` | `string` | No | An icon to display next to the link. Accepts a built-in [icon key](../components/icons.mdx#built-in-icons) (Phosphor or Simple Icons) or a [custom URL](../components/icons.mdx#custom-icons). |
| `newTab` | `boolean` | No | Whether to open the link in a new tab (defaults to `false`) |
#### Group dropdowns
A group collects several links into a single dropdown.
```json
{
"type": "group",
"title": "Resources",
"icon": "phosphor/regular/books",
"children": [
{
"type": "link",
"title": "API Reference",
"to": "/reference"
},
{
"type": "link",
"title": "Changelog",
"to": "/changelog"
}
]
}
```
| Property | Type | Required | Description |
| ---------- | ------------------------------ | -------- | ------------------------------------------------------ |
| `type` | `"group"` | Yes | Must be `"group"` |
| `title` | `string` | Yes | The display text for the dropdown |
| `children` | `array` | Yes | The links inside the dropdown |
| `align` | `"start" \| "center" \| "end"` | No | Which region the group sits in (defaults to `"start"`) |
| `icon` | `string` | No | An icon to display next to the group. Accepts a built-in [icon key](../components/icons.mdx#built-in-icons) (Phosphor or Simple Icons) or a [custom URL](../components/icons.mdx#custom-icons). |
`children` accepts link items only. Each child takes the same properties as a [header link](#header-links).
To lay a dropdown out in titled columns, give its children a `section`. See [Mega Menus](mega-menus.md).
#### Version selector
Places the [version](versions.md) dropdown at a specific position in the header.
```json
{
"type": "version-selector",
"align": "end"
}
```
| Property | Type | Required | Description |
| -------- | ------------------------------ | -------- | --------------------------------------------------------- |
| `type` | `"version-selector"` | Yes | Must be `"version-selector"` |
| `align` | `"start" \| "center" \| "end"` | No | Which region the selector sits in (defaults to `"start"`) |
The selector only renders when your project defines more than one version. If you do not add this item, it renders next to your logo.
## Sidebar
The `navigation.sidebar` array defines links that appear in the footer of the sidebar navigation. These are useful for adding authentication links, support resources, or other important links that should be easily accessible from any page.
### Example
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"navigation": {
"sidebar": [
{
"title": "Log in",
"to": "https://dashboard.scalar.com/login",
"icon": "phosphor/regular/sign-in"
}
],
"routes": {
// ...
}
}
}
```
### Properties
| Property | Type | Required | Description |
| -------- | -------------------- | -------- | ---------------------------------------- |
| `title` | `string` | Yes | The display text for the sidebar link |
| `to` | `string` | Yes | The route path or URL the link points to |
| `icon` | `string` | No | An icon to display next to the link. Accepts a built-in [icon key](../components/icons.mdx#built-in-icons) (Phosphor or Simple Icons) or a [custom URL](../components/icons.mdx#custom-icons). |
| `newTab` | `boolean` | No | Whether to open the link in a new tab |
## Tabs
The `navigation.tabs` array defines tabs that appear in the navigation area. Tabs provide a way to organize and highlight specific sections of your documentation, such as API references, that you want users to access quickly.
Tabs and a header work together, and you do not need both. If you use tabs without a header, your [logo](site-config.md#logo) renders in the tab bar.
### Example
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"navigation": {
"tabs": [
{
"title": "API",
"to": "/api",
"icon": "phosphor/regular/plug"
}
],
"routes": {
// ...
}
}
}
```
### Properties
| Property | Type | Required | Description |
| -------- | -------- | -------- | -------------------------------------- |
| `title` | `string` | Yes | The display text for the tab |
| `to` | `string` | Yes | The route path or URL the tab links to |
| `icon` | `string` | No | An icon to display next to the tab. Accepts a built-in [icon key](../components/icons.mdx#built-in-icons) (Phosphor or Simple Icons) or a [custom URL](../components/icons.mdx#custom-icons). |
### Multiple Tabs
You can define multiple tabs to provide quick access to different sections:
```json
"tabs": [
{
"title": "API",
"to": "/tools/api",
"icon": "phosphor/regular/plug"
},
{
"title": "SDKs",
"to": "/products/sdk-generator",
"icon": "phosphor/regular/package"
}
]
```
## Pages
Pages render markdown content from files in your repository. They are the most common route type and form the foundation of your documentation.
```json
"/getting-started": {
"type": "page",
"title": "Getting Started",
"filepath": "docs/getting-started.md"
}
```
### Properties
| Property | Type | Required | Description |
| --------------- | ---------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type` | `"page"` | Yes | Must be `"page"` |
| `groups` | `string[]` | No | Show the entry to visitors with a matching group. See [Personalization](personalization.md#filter-navigation). |
| `title` | `string` | No | The display text in the navigation |
| `filepath` | `string` | Yes | Relative path to the markdown file |
| `description` | `string` | No | A description for SEO and metadata |
| `icon` | `string` | No | An icon to display next to the page. Accepts a built-in [icon key](../components/icons.mdx#built-in-icons) (Phosphor or Simple Icons) or a [custom URL](../components/icons.mdx#custom-icons). |
| `showInSidebar` | `boolean` | No | Whether to show the page in the sidebar (defaults `true`) |
| `hidden` | `boolean` | No | Fully hide the page: no sidebar entry, no sitemap entry, and `noindex` (defaults `false`) |
| `layout` | `object` | No | Layout configuration options |
### Hidden pages
There are two ways to keep a page out of your navigation, depending on whether the page should still be discoverable by search engines.
#### Truly hidden pages with `hidden`
Set `hidden` to `true` to fully hide a page. The page is:
- removed from the sidebar navigation,
- excluded from the generated `sitemap.xml`, and
- rendered with a `` tag so search engines do not index it.
The page stays reachable at its URL, which makes it a good fit for unlisted content like internal notes, early drafts, or pages you only want to share by direct link.
```json
"/internal-notes": {
"type": "page",
"title": "Internal Notes",
"filepath": "docs/internal-notes.md",
"hidden": true
}
```
If you need to override the automatic `noindex` for a hidden page, an explicit `robots` meta tag in the page's `head` configuration takes precedence.
Note that the site's `robots.txt` intentionally keeps allowing crawlers: they must be able to fetch the page to see the `noindex` tag, and URLs blocked by `robots.txt` can still show up in search results (title-only) when external sites link to them.
#### Sidebar-only hiding with `showInSidebar`
Set `showInSidebar` to `false` to hide a page from the sidebar navigation only. This is purely cosmetic: the page remains in the sitemap and stays indexable by search engines. This is useful for special pages like landing pages, promotional content, or forms that should not clutter the main navigation but should still be found through search.
```json
"/enterprise": {
"type": "page",
"title": "Enterprise",
"filepath": "docs/enterprise.md",
"showInSidebar": false
}
```
Users can still navigate to `/enterprise` directly, but the page will not appear in the sidebar. To make a page visible in the sidebar again, remove the `showInSidebar` property or set it to `true`.
In short: use `hidden: true` when the page should be invisible to search engines, and `showInSidebar: false` when it should only be invisible in the sidebar.
### Layout Options
Pages support layout configuration to customize how they are displayed. These options override the site-wide defaults in [`siteConfig.layout`](site-config.md#layout) for a single page:
```json
"/introduction": {
"type": "page",
"title": "Introduction",
"filepath": "docs/introduction.md",
"layout": {
"toc": false,
"sidebar": false
}
}
```
| Option | Type | Default | Description |
| ------------- | --------- | ------- | ---------------------------------------- |
| `toc` | `boolean` | `true` | Whether to show the table of contents |
| `sidebar` | `boolean` | `true` | Whether to show the sidebar navigation |
| `tabs` | `boolean` | `true` | Whether to show the navigation tabs |
| `header` | `boolean` | — | Whether to show the header. Falls back to the site-level [`layout.header`](site-config.md#layout) option |
| `pageTitle` | `boolean` | `true` | Whether to show the page title |
| `pageActions` | `boolean` | `true` | Whether to show page actions |
| `pageNav` | `boolean` | `true` | Whether to show previous and next page links at the bottom of the page |
| `lastUpdated` | `boolean` | `false` | Whether to show the date the page last changed, above the previous and next links. See [Last updated date](site-config.md#last-updated-date) |
| `feedback` | `boolean` | — | Whether to ask readers if the page was helpful. Falls back to the site-level [`layout.feedback`](site-config.md#layout) option. See [Page feedback](site-config.md#page-feedback) |
| `search` | `object` | — | Search configuration for this page |
| `colorSchemeToggle` | `"sidebar" \| "header" \| "tabs" \| false` | — | Where to show the light/dark toggle. Falls back to the site-level [`layout.colorSchemeToggle`](site-config.md#where-the-toggle-appears) option |
### Search Options
You can configure the search behavior on a per-page basis:
```json
"/api-reference": {
"type": "page",
"title": "API Reference",
"filepath": "docs/api-reference.md",
"layout": {
"search": {
"enabled": true,
"position": "sidebar"
}
}
}
```
| Option | Type | Default | Description |
| ---------- | ------------------------- | ---------- | --------------------------------------- |
| `enabled` | `boolean` | `true` | Enable or disable search for this page |
| `position` | `"header" \| "sidebar"` | `"header"` | The position of the search bar |
### Example with All Options
```json
"/pricing": {
"type": "page",
"title": "Pricing",
"filepath": "documentation/guides/pricing.md",
"description": "Explore our pricing plans",
"icon": "phosphor/regular/coin-vertical",
"layout": {
"toc": false
}
}
```
## API References
Scalar supports three ways to generate API references:
1. using a local file,
2. the [Registry](../../registry/index.md), or
3. remote URLs.
An API reference entry accepts `type: "openapi"` or `type: "asyncapi"`. Use whichever matches your document — the format is detected automatically.
### 1. Files
Reference an API document stored in your repository by specifying a relative path from your configuration root:
```json
{
"/api": {
"type": "openapi",
"title": "My API",
"filepath": "docs/api-reference/openapi.yaml",
"icon": "phosphor/regular/plug"
}
}
```
### 2. Registry
Upload your API document to the [Registry](../../registry/index.md), then reference it by namespace and slug:
```bash
scalar auth login
scalar registry publish ./openapi.yaml \
--namespace my-organization \
--slug your-api
```
```json
"/api": {
"type": "openapi",
"title": "My API",
"namespace": "my-organization",
"slug": "your-api",
// "version": "1.0.0"
}
```
When someone updates that API document in the Registry, Scalar republishes any connected Docs project that references it. This keeps your API documentation up to date automatically.
### 3. URL
Point an API reference at a document hosted somewhere else:
```json
"/api": {
"type": "openapi",
"title": "My API",
"url": "https://example.com/openapi.json"
}
```
Scalar fetches the URL while your documentation is being built and writes the document into the deployed site. It is not fetched again when a reader opens the page, so a change to the remote document shows up on your next deployment — push a commit, or start a new deployment from the [Scalar Dashboard](https://dashboard.scalar.com/).
If you want the reference to follow your API without a deployment, publish the document to the [Registry](../../registry/index.md) and reference it by namespace and slug instead. Updating it there republishes every Docs project that points at it.
Some things worth knowing before you use a URL:
- **The URL has to be publicly reachable.** The build sends a plain `GET` with no authentication headers, from Scalar's build infrastructure rather than from your reader's browser, so a document behind a login, a VPN, or an IP allowlist will not load. Anything you put in the URL — a query-string token included — is stored in your `scalar.config.json`, so treat it as readable by anyone who can read the repository.
- **The document should be self-contained.** `$ref`s pointing at absolute `https://` URLs are followed and bundled in, but relative ones such as `./schemas/pet.yaml` are not — there is no local directory to resolve them against. They are left as written, and the parts of the reference that depend on them render empty.
### AsyncAPI
To document an event-driven API, use `type: "asyncapi"` and point it at your AsyncAPI document. This works with files, the Registry, or a remote URL, exactly like an `openapi` entry:
```json
"/events": {
"type": "asyncapi",
"title": "My Events API",
"filepath": "docs/api-reference/asyncapi.yaml"
}
```
The entry renders your channels, operations, and messages in the sidebar. See [AsyncAPI](../../../asyncapi.md) for what gets rendered and how the document maps onto the reference.
### Properties
| Property | Type | Required | Description |
| ------------ | -------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type` | `"openapi" \| "asyncapi"` | Yes | Marks the entry as an API reference |
| `groups` | `string[]` | No | Show the entry to visitors with a matching group. See [Personalization](personalization.md#filter-navigation). |
| `title` | `string` | No | The display text in the navigation |
| `filepath` | `string` | No | Relative path to the API document |
| `url` | `string` | No | URL the API document is fetched from at build time |
| `namespace` | `string` | No | Registry namespace (when using Registry) |
| `slug` | `string` | No | Registry slug (when using Registry) |
| `version` | `string` | No | Registry version (when using Registry) |
| `icon` | `string` | No | An icon to display next to the reference. Accepts a built-in [icon key](../components/icons.mdx#built-in-icons) (Phosphor or Simple Icons) or a [custom URL](../components/icons.mdx#custom-icons). |
| `mode` | `"flat" \| "nested" \| "folder"` | No | How the API reference is displayed in the sidebar |
| `singlePage` | `boolean` | No | Render all operations on a single page (defaults to `false`) |
| `hidden` | `boolean` | No | Fully hide the API reference and all its generated pages (defaults to `false`) |
| `config` | `object` | No | API Reference configuration options |
### Display Modes
- `folder` (default): Shows a single level of links with a folder icon
- `flat`: Shows a single level of links with a section title
- `nested`: Shows a sub-sidebar with breadcrumbs for deep navigation
### Single Page Mode
By default, Docs creates a separate page for each API operation. Set `singlePage` to `true` to render all operations on a single page instead:
```json
"/api": {
"type": "openapi",
"title": "My API",
"filepath": "docs/api-reference/openapi.yaml",
"singlePage": true
}
```
This is useful when you want a scrollable, single-page API reference similar to traditional API documentation layouts.
### Hiding an API Reference
Set `hidden` to `true` to fully hide an API reference. The setting cascades to every page generated from the API document — all operation, tag, model, and webhook pages are removed from the sidebar, excluded from `sitemap.xml`, and rendered with a `noindex` meta tag. The pages stay reachable at their URLs, so you can still share them by direct link. See [Hidden pages](#hidden-pages) for details on how `hidden` compares to `showInSidebar`.
```json
"/internal-api": {
"type": "openapi",
"title": "Internal API",
"filepath": "docs/internal-api/openapi.yaml",
"hidden": true
}
```
### API Reference configuration
When you add an API reference route (`type: "openapi"` or `type: "asyncapi"`) in your navigation, you can pass API Reference options by adding a `config` object. Only the options listed below can be set here. Other [API Reference options](../../../configuration.md), like `theme` or `layout`, are ignored here. Set the site's theme with [`siteConfig.theme`](themes.md) instead.
Example:
```json
// scalar.config.json
"/api": {
"type": "openapi",
"title": "My API",
"url": "https://example.com/openapi.json",
"mode": "nested",
"config": {
"authentication": {
"preferredSecurityScheme": "httpBasic",
"securitySchemes": {
"httpBasic": {
"type": "http",
"scheme": "basic",
"username": "my-username"
}
}
}
}
}
```
- [`authentication`](../../../configuration.md#authentication)
- [`baseServerURL`](../../../configuration.md#baseserverurl)
- [`defaultHttpClient`](../../../configuration.md#defaulthttpclient)
- [`defaultOpenAllTags`](../../../configuration.md#defaultopenalltags)
- [`documentDownloadType`](../../../configuration.md#documentdownloadtype)
- [`expandAllModelSections`](../../../configuration.md#expandallmodelsections)
- [`expandAllResponses`](../../../configuration.md#expandallresponses)
- [`hiddenClients`](../../../configuration.md#hiddenclients)
- [`hideClientButton`](../../../configuration.md#hideclientbutton)
- [`hideModels`](../../../configuration.md#hidemodels)
- [`hideTestRequestButton`](../../../configuration.md#hidetestrequestbutton)
- [`operationTitleSource`](../../../configuration.md#operationtitlesource)
- [`orderRequiredPropertiesFirst`](../../../configuration.md#orderrequiredpropertiesfirst)
- [`orderSchemaPropertiesBy`](../../../configuration.md#orderschemapropertiesby)
- [`proxyUrl`](../../../configuration.md#proxyurl)
- [`servers`](../../../configuration.md#servers)
- [`showOperationId`](../../../configuration.md#showoperationid)
Each option works the same way as in the API Reference, except that `proxyUrl` defaults to `https://proxy.scalar.com`.
## Groups
Groups allow you to organize related pages, API references, and links into collapsible sections in your navigation. They can be nested to create multi-level hierarchies.
```json
"/products": {
"type": "group",
"title": "Products",
"mode": "flat",
"icon": "phosphor/regular/package",
"children": {
"/docs": {
"type": "page",
"title": "Documentation",
"filepath": "docs/documentation.md"
},
"/api": {
"type": "openapi",
"title": "API Reference",
"filepath": "openapi.yaml"
}
}
}
```
### Properties
| Property | Type | Required | Description |
| ---------- | -------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type` | `"group"` | Yes | Must be `"group"` |
| `groups` | `string[]` | No | Show a nested group and its children to visitors with a matching group; unsupported on top-level route sections. See [Personalization](personalization.md#filter-navigation). |
| `title` | `string` | No | The display text in the navigation |
| `children` | `object` | Yes | An object containing nested routes |
| `mode` | `"flat" \| "nested" \| "folder"` | No | How the group is displayed |
| `icon` | `string` | No | An icon to display next to the group. Accepts a built-in [icon key](../components/icons.mdx#built-in-icons) (Phosphor or Simple Icons) or a [custom URL](../components/icons.mdx#custom-icons). |
| `page` | `object` | No | A page to navigate to when clicking the folder (folder mode only) |
| `open` | `boolean` | No | Whether the folder is expanded by default (folder mode only) |
| `hidden` | `boolean` | No | Fully hide the group and everything nested under it (defaults to `false`) |
### Display Modes
Groups support three display modes:
- **`flat`**: Shows a section title with child links directly beneath it. Ideal for top-level categories.
- **`nested`**: Shows a sub-sidebar with breadcrumbs for deep navigation. Good for complex documentation structures.
- **`folder`**: (default): Shows a single level of links with a folder icon. Suitable for simple groupings.
### Hiding Groups
Set `hidden` to `true` on a group to fully hide it along with everything nested under it — child pages, nested groups, and any API references. All affected pages are removed from the sidebar, excluded from `sitemap.xml`, and rendered with a `noindex` meta tag, while remaining reachable at their URLs. See [Hidden pages](#hidden-pages) for details on how `hidden` compares to `showInSidebar`.
This works at both levels: on a top-level route section directly under `navigation.routes` and on a group nested inside another group, with the same cascade to every page underneath. Since a top-level route section has no sidebar row of its own, `hidden` there only affects indexing — and any [tabs](#tabs) or [header links](#header) pointing at that section are configured separately and are not removed automatically.
```json
"/internal": {
"type": "group",
"title": "Internal",
"hidden": true,
"children": {
"/runbooks": {
"type": "page",
"title": "Runbooks",
"filepath": "docs/internal/runbooks.md"
}
}
}
```
### Nesting Groups
Groups can contain other groups to create deep navigation hierarchies:
```json
"/products": {
"type": "group",
"title": "Products",
"mode": "flat",
"children": {
"/docs": {
"type": "group",
"title": "Docs",
"mode": "nested",
"icon": "phosphor/regular/book",
"children": {
"getting-started": {
"type": "page",
"title": "Getting Started",
"filepath": "docs/getting-started.md"
},
"configuration": {
"type": "group",
"title": "Configuration",
"mode": "flat",
"children": {
"navigation": {
"type": "page",
"title": "Navigation",
"filepath": "docs/configuration/navigation.md"
}
}
}
}
}
}
}
```
### Folder Landing Pages
Folders can have an associated landing page using the `page` property. When a user clicks on the folder title in the sidebar, they navigate to this page instead of just expanding the folder. This is useful for sections that need both an overview page and child pages.
```json
"/company": {
"type": "group",
"title": "Company",
"mode": "folder",
"icon": "phosphor/regular/building",
"page": {
"type": "page",
"title": "About Us",
"filepath": "docs/company/index.md"
},
"children": {
"/team": {
"type": "page",
"title": "Our Team",
"filepath": "docs/company/team.md"
},
"/careers": {
"type": "page",
"title": "Careers",
"filepath": "docs/company/careers.md"
}
}
}
```
In this example, clicking "Company" in the sidebar navigates to the "About Us" page (`docs/company/index.md`), while the folder can still be expanded to show "Our Team" and "Careers" as child pages.
The `page` property accepts the same configuration as a regular page route:
| Property | Type | Required | Description |
| ------------- | --------- | -------- | ---------------------------------- |
| `type` | `"page"` | Yes | Must be `"page"` |
| `title` | `string` | No | The display text for the page |
| `filepath` | `string` | Yes | Relative path to the markdown file |
| `description` | `string` | No | A description for SEO and metadata |
### Default Folder State
By default, folders start in a collapsed state. Use the `open` property to have a folder expanded when the page loads:
```json
"/guides": {
"type": "group",
"title": "Guides",
"mode": "folder",
"open": true,
"children": {
"/quickstart": {
"type": "page",
"title": "Quickstart",
"filepath": "docs/guides/quickstart.md"
},
"/advanced": {
"type": "page",
"title": "Advanced Usage",
"filepath": "docs/guides/advanced.md"
}
}
}
```
## Links
Links allow you to add external URLs to your navigation. Unlike pages that render content from files, links redirect users to external resources.
```json
"/github": {
"type": "link",
"title": "GitHub",
"url": "https://github.com/scalar/scalar",
"icon": "phosphor/regular/github-logo"
}
```
### Properties
| Property | Type | Required | Description |
| -------- | ---------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type` | `"link"` | Yes | Must be `"link"` |
| `groups` | `string[]` | No | Show the entry to visitors with a matching group. See [Personalization](personalization.md#filter-navigation). |
| `title` | `string` | No | The display text in the navigation |
| `url` | `string` | Yes | The external URL to link to |
| `icon` | `string` | No | An icon to display next to the link. Accepts a built-in [icon key](../components/icons.mdx#built-in-icons) (Phosphor or Simple Icons) or a [custom URL](../components/icons.mdx#custom-icons). |
| `hidden` | `boolean` | No | Hide the link from the sidebar (defaults to `false`) |
Since a link points to an external URL, there is no page to exclude from the sitemap or deindex — on links, `hidden: true` only removes the sidebar entry. The option exists on all route types for consistency.
### Example
Here is an example of a group containing multiple links:
```json
"/contact": {
"type": "group",
"title": "Let's Chat",
"mode": "flat",
"children": {
"/github": {
"title": "GitHub",
"icon": "phosphor/regular/github-logo",
"url": "https://github.com/scalar/scalar",
"type": "link"
},
"/email": {
"title": "Support",
"icon": "phosphor/regular/envelope",
"url": "mailto:support@scalar.com",
"type": "link"
},
"/demo": {
"title": "Book a Demo",
"icon": "phosphor/regular/monitor",
"url": "https://scalar.cal.com/forms/142d1e65-97d2-4d03-94c3-96f98ddef95a",
"type": "link"
}
}
}
```
Links can also be used for `mailto:` URLs to create email links, or any other valid URL scheme.
# Mega Menus
A mega menu is a dropdown in the [header](navigation.md#header) or the [tab bar](navigation.md#tabs) that lays its links out in titled columns instead of a single list. Use one when a dropdown has grown past six or so links and readers need a second level of grouping to find what they want.
There is no layout switch to turn on. A dropdown becomes a mega menu the moment one of its links names the column it sits under with `section`.
## How it works
Every dropdown is a flat, ordered list of links. A mega menu is a rendering of that list, not a nesting level:
- Give a link a `section` to name the column heading it sits under.
- Consecutive links that share a `section` form one column, titled with that value.
- The number of columns is the number of those runs. There is no column count to set.
- Links that name no `section` form their own untitled column, at the position they were authored.
Because the columns are just the list read in order, the same list also drives the collapsed mobile menu, so there is never a second structure to keep in sync.
## Header mega menu
Add `section` to the children of a [group](navigation.md#group-dropdowns) in `navigation.header`:
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"navigation": {
"header": [
{ "type": "link", "title": "Home", "to": "/" },
{
"type": "group",
"title": "Resources",
"children": [
{
"type": "link",
"title": "API Reference",
"to": "/reference",
"icon": "phosphor/regular/code",
"section": "Documentation"
},
{
"type": "link",
"title": "Guides",
"to": "/guides",
"icon": "phosphor/regular/compass",
"section": "Documentation"
},
{
"type": "link",
"title": "About",
"to": "https://scalar.com",
"newTab": true,
"section": "Company"
},
{
"type": "link",
"title": "Status",
"to": "https://status.scalar.com",
"newTab": true,
"section": "Company"
},
{
"type": "link",
"title": "Everything else",
"to": "/more"
}
]
}
],
"routes": {
// ...
}
}
}
```
The **Resources** dropdown renders three columns, left to right:
| Documentation | Company | _(no heading)_ |
| ------------- | ------- | --------------- |
| API Reference | About | Everything else |
| Guides | Status | |
Links inside a mega menu take the same properties as any [header link](navigation.md#header-links): `title`, `to`, `icon`, `newTab`, and `style`. The group itself keeps its `title`, `icon`, and `align`.
## Tabs mega menu
The tab bar accepts dropdowns too. A tab group is `{ "type": "group", "title", "icon", "children" }`, and each child is a tab link with an optional `section`:
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"navigation": {
"tabs": [
{ "title": "Home", "to": "/" },
{
"type": "group",
"title": "Platform",
"children": [
{ "title": "API Reference", "to": "/reference", "section": "Build" },
{ "title": "Guides", "to": "/guides", "section": "Build" },
{ "title": "Scalar Website", "to": "https://scalar.com", "section": "Operate" }
]
}
],
"routes": {
// ...
}
}
}
```
Tab links have no `type` key. They take `title`, `to`, `icon`, `newTab`, and `section`, exactly like a top-level tab plus the column heading.
## The `section` property
| Property | Type | Required | Description |
| --------- | -------- | -------- | --------------------------------------------------------------------------------------------- |
| `section` | `string` | No | The column heading a link sits under. Applies to children of a `group` in `navigation.header` or `navigation.tabs`. |
- It must be a non-empty string. An empty string fails validation. To leave a link out of any titled column, omit the key instead.
- It is ignored on links that sit directly in the header band or the tab bar rather than inside a group.
- It is an annotation on each link, so renaming a column means changing the value on every link in that run.
If your config declares `"$schema": "https://cdn.scalar.com/schema/scalar-config-next.json"`, your editor will autocomplete `section` on dropdown children.
## Rules to know
- **Order is authored order.** Columns appear left to right in the order their first link appears in `children`, and links stack top to bottom within a column in the same order.
- **Keep a column's links together.** Grouping is by consecutive run, not by name. Two runs with the same heading that are separated by another section render as two separate columns with the same heading.
- **Untitled columns are allowed.** A link with no `section` is its own column with no heading. A common pattern is a trailing untitled column for one or two leftovers, as in the header example above.
- **One sectioned link is enough.** As soon as any child names a section the whole dropdown switches to columns. The unsectioned links become untitled columns at their positions, so decide up front whether a dropdown is a list or a mega menu.
- **Plain dropdowns are unchanged.** A group with no `section` on any child renders as the single-column list it always has. You can mix plain dropdowns and mega menus in the same band.
- **Only links make columns.** The deprecated `spacer` child inside a dropdown renders nothing and does not split a column.
## Appearance and responsive behavior
- The panel opens on hover and on click, like every other dropdown in the header.
- Column headings render as small, muted labels above their links. Link icons show inside the columns.
- Columns share the panel width equally. Up to four columns sit side by side on a wide screen. Beyond that, columns wrap onto a new row.
- As the viewport narrows the grid drops columns on its own, down to a single stacked column on phones, and the panel never pushes the page wider than the screen.
- Below 1000px the header links move into the mobile menu drawer. A header mega menu becomes a collapsible folder there, with each column shown as a titled section in the same order.
- The tab bar stays visible on phones. A tab mega menu opens as one column, with the headings and links stacked in authored order.
## Editing in the dashboard
You can build a mega menu without touching the config file. In the docs editor, open the header settings and pick **Header** or **Tabs**, then click a dropdown to open it.
1. Click **Add column**. This adds a new link under a provisional heading such as `Column 1` and opens it so you can set its title and target.
2. Rename the column with the **Column heading** input above it. Renaming rewrites the heading on every link in that column.
3. Use **Move up** and **Move down** to reorder links. Moving a link past the edge of its column moves it into the neighbouring column, and it takes on that column's heading.
4. **Add link** adds a link with no heading, which appears as an untitled column at the end. Move it up into a column to file it under a heading.
Clearing every column heading turns the dropdown back into a plain list. Removing the last link in a column removes the column, because a column exists only while a link names it. The preview beside the panel shows the columns as readers will see them.
## Validating and previewing with the CLI
`scalar project check-config` accepts `section` and reports an error that names the field if a heading is empty:
```bash
scalar project check-config scalar.config.json
```
`scalar project preview` renders mega menus locally:
```bash
scalar project preview
```
Dropdown mega menus ship in the CLI release after 2.2.0. On an older CLI the field is ignored and the dropdown renders as a single-column list, so a config that uses `section` still builds.
## Compatibility
The feature is purely additive. A config with no `section` anywhere parses and renders exactly as before, and adding `section` never changes where a link sits in the collapsed menu.
## Tips
- Keep headings to one or two words. They render in a small label style and are there to orient, not to explain.
- Two to four columns with three to six links each is the range that reads well. Past that, split the dropdown into two.
- Put the column readers reach for most on the left. It is the first one both sighted readers and screen readers meet.
- Give an untitled column a single, obvious purpose, such as one or two catch-all links at the end.
# Versions
The `versions` property in your `scalar.config.json` allows you to create multiple versions of your documentation. This is useful for maintaining documentation for different API versions, product releases, or major updates while keeping everything organized under a single domain.
When you use the `versions` property, each version gets its own complete navigation structure, and users can switch between versions using a version selector in the UI.
## Basic structure
Instead of using the `navigation` property at the root level, you use `versions` which is an object where each key is the version identifier and each value is a complete navigation configuration.
You must always have a version with the key `default`. This is the version that is shown by default when users visit your documentation. Additional versions can use any identifier you like (for example `v1`, `v2`, `legacy`).
Inside each version's `routes`, wrap your pages in a top-level group so they render correctly in the sidebar:
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"info": {
"title": "My API Documentation"
},
"versions": {
"default": {
"title": "Version 2.0",
"routes": {
"/": {
"type": "group",
"title": "Documentation",
"children": {
"/": {
"type": "page",
"title": "Introduction",
"filepath": "docs/v2/introduction.md"
},
"/api": {
"type": "openapi",
"title": "API Reference",
"filepath": "docs/v2/openapi.yaml"
}
}
}
}
},
"v1": {
"title": "Version 1.0",
"routes": {
"/": {
"type": "group",
"title": "Documentation",
"children": {
"/": {
"type": "page",
"title": "Introduction",
"filepath": "docs/v1/introduction.md"
},
"/api": {
"type": "openapi",
"title": "API Reference",
"filepath": "docs/v1/openapi.yaml"
}
}
}
}
}
}
}
```
## Version configuration
Each version entry supports the same properties as a `navigation` object:
| Property | Type | Required | Description |
| --------- | -------- | -------- | -------------------------------------------------- |
| `title` | `string` | No | Display title for the version in the selector |
| `routes` | `object` | Yes | Navigation routes for this version |
| `header` | `array` | No | Header links for this version |
| `sidebar` | `array` | No | Sidebar footer links for this version |
| `tabs` | `array` | No | Navigation tabs for this version |
The `default` version key is required and represents the version shown by default. Other version keys (for example `v2`, `v1`, `beta`) appear in the version selector dropdown. The optional `title` property provides a more descriptive label for each entry.
## Example with shared and version-specific content
You can organize your documentation to share common pages across versions while keeping version-specific API references separate. Remember to keep the top-level group inside each version's `routes`:
```json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"info": {
"title": "Acme API"
},
"siteConfig": {
"subdomain": "acme-api",
"theme": "default"
},
"versions": {
"default": {
"title": "Version 2.0 (Latest)",
"tabs": [
{
"title": "API Reference",
"to": "/api",
"icon": "phosphor/regular/plug"
}
],
"routes": {
"/": {
"type": "group",
"title": "Getting Started",
"mode": "flat",
"children": {
"": {
"type": "page",
"title": "Introduction",
"filepath": "docs/introduction.md"
},
"/quickstart": {
"type": "page",
"title": "Quickstart",
"filepath": "docs/quickstart.md"
},
"/authentication": {
"type": "page",
"title": "Authentication",
"filepath": "docs/v2/authentication.md"
}
}
},
"/api": {
"type": "openapi",
"title": "API Reference",
"filepath": "docs/v2/openapi.yaml",
"mode": "nested"
}
}
},
"v1": {
"title": "Version 1.0 (Legacy)",
"tabs": [
{
"title": "API Reference",
"to": "/api",
"icon": "phosphor/regular/plug"
}
],
"routes": {
"/": {
"type": "group",
"title": "Getting Started",
"mode": "flat",
"children": {
"": {
"type": "page",
"title": "Introduction",
"filepath": "docs/introduction.md"
},
"/quickstart": {
"type": "page",
"title": "Quickstart",
"filepath": "docs/v1/quickstart.md"
},
"/authentication": {
"type": "page",
"title": "Authentication",
"filepath": "docs/v1/authentication.md"
}
}
},
"/api": {
"type": "openapi",
"title": "API Reference",
"filepath": "docs/v1/openapi.yaml",
"mode": "nested"
}
}
}
}
}
```
## Version ordering
The `default` version is always shown first when users visit your documentation. Other versions appear in the selector in the order they are defined in the configuration.
## When to use versions vs. multiple projects
Use **versions** when:
- You have multiple versions of the same API or product
- Users need to switch between versions frequently
- The documentation structure is similar across versions
Use **multiple projects** (separate repositories with `subpath`) when:
- You have completely different products or APIs
- The documentation structure is significantly different
- Teams manage documentation independently
## Migration from single navigation
To convert an existing configuration with `navigation` to use `versions`:
1. Rename `navigation` to `versions`
2. Wrap your existing navigation configuration under the `default` key
3. Add a `title` to describe the version
**Before:**
```json
{
"scalar": "2.0.0",
"navigation": {
"routes": {
"/": {
"type": "group",
"title": "Documentation",
"children": {
"/": { "type": "page", "title": "Intro", "filepath": "docs/intro.md" }
}
}
}
}
}
```
**After:**
```json
{
"scalar": "2.0.0",
"versions": {
"default": {
"title": "Version 1.0",
"routes": {
"/": {
"type": "group",
"title": "Documentation",
"children": {
"/": { "type": "page", "title": "Intro", "filepath": "docs/intro.md" }
}
}
}
}
}
}
```
You can then add additional versions alongside `default` as needed.
# Redirects
Redirects allow you to automatically redirect users from one URL to another in your Docs project. This is useful for handling URL changes, deprecated pages, migrating from other platforms, or creating shortcuts to commonly accessed content.
## Configuration
Redirects are configured in your `scalar.config.json` file under the `siteConfig.routing.redirects` section:
```json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"siteConfig": {
"routing": {
"redirects": [
{
"from": "/old-path",
"to": "/new-path"
}
]
}
}
}
```
### Wildcard Redirects
You can use wildcards to redirect multiple paths with a single rule:
```json
{
"from": "/old-path/:wildcard",
"to": "/new-path"
}
```
This will redirect `/old-path/whatever-that-is` to `/new-path`.
Or, if you have a specific prefix:
```json
{
"from": "/old-path/12345-:wildcard",
"to": "/new-path"
}
```
This will redirect `/old-path/12345-whatever-that-is` to `/new-path`.
### Regex Redirects
You can even use regular expressions in your redirects:
```json
{
"from": "/old-path/:pathMatch(.*)*",
"to": "/new-path"
}
```
# Themes
The `theme` property sets the visual appearance of your documentation site. Scalar provides a collection of built-in themes to match your brand or style preferences.
## Configuration
Set the theme in the `siteConfig` object of your `scalar.config.json` file:
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"siteConfig": {
"theme": "purple"
}
}
```
## Available Themes
Docs sites support these built-in themes: `default`, `alternate`, `moon`, `purple`, `solarized`, `bluePlanet`, `deepSpace`, `saturn`, `kepler`, `mars`, `laserwave`, `elysiajs`, and `fastify`. The names `blue-planet`, `deep-space`, and `kepler-11e` work too.
You can also set `theme` to:
- the path to a `.css` file in your project, like `"./theme.css"`
- the slug of one of your team's custom themes
Your documentation site and your API references share the same theme system. To see what each theme looks like, and to customize colors, fonts, and layouts with CSS variables, see the [Themes reference](../../../themes.md).
# Social Cards
Every page of your docs site gets a social card: the 1200 × 630 image shown when a link is shared on Slack, X, LinkedIn, iMessage, Discord and anywhere else that reads Open Graph tags. Scalar draws one from your theme, logo and page title. A template replaces that design with your own — a TSX or JSX file in your repository, run once per page when the site builds.
## Setting up
In the [Scalar Dashboard](https://dashboard.scalar.com), open **Settings → Appearance → Social card** and choose **Customize**. That writes a starter template to `og/card.tsx`, configures it, and opens it in the editor next to a live preview.
To set it up by hand, point `siteConfig.og.imageTemplate` at the file. The path is relative to `scalar.config.json`.
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"siteConfig": {
"og": {
"imageTemplate": "./og/card.tsx"
}
}
}
```
Remove the `og` block to go back to the built-in card; your template file stays in the repository. An `og:image` set in [`siteConfig.head`](site-config.md#head) applies to every page and overrides generated cards, templates included.
## Writing a template
A template default-exports a pure function: it takes the page's details as props and returns the card as JSX. Hooks, state, effects and data fetching are not available.
```tsx
// og/card.tsx
export default function SocialCard({ title, description, colors }) {
return (
{title}
{description ? (
{description}
) : null}
)
}
```
In the Scalar editor, `OgTemplateProps`, `OgCss`, `OgColors` and `OgMode` are declared for you with no import. Elsewhere, declare the props yourself — the build compiles the template without typechecking it.
### Props
| Prop | Type | Description |
| ------------- | ------------------- | ------------------------------------------------------------------------------- |
| `title` | `string` | The page title. |
| `description` | `string?` | The page description, when it has one. |
| `breadcrumb` | `string?` | The section the page belongs to, as shown above the title on the built-in card. |
| `path` | `string` | The page's route, such as `/guides/authentication`. |
| `colors` | `OgColors` | Colors from your theme. See below. |
| `logo` | `string \| null` | Your site logo as a data URI, or `null` when there isn't one. |
| `mode` | `'light' \| 'dark'` | The color scheme the card is drawn in. |
Text arrives in full. Nothing is shortened for you, so long titles and descriptions need a line limit.
### Colors
`colors` holds your theme's variables, resolved for the scheme in `siteConfig.colorScheme.default` — dark unless that is `light`. A variable your theme does not set falls back to the default Scalar theme.
| Color | Theme variable |
| ---------- | ---------------------------- |
| `color1` | `--scalar-color-1` |
| `color2` | `--scalar-color-2` |
| `color3` | `--scalar-color-3` |
| `bg1` | `--scalar-background-1` |
| `bg2` | `--scalar-background-2` |
| `bg3` | `--scalar-background-3` |
| `accent` | `--scalar-color-accent` |
| `bgAccent` | `--scalar-background-accent` |
| `border` | `--scalar-border-color` |
## What Satori supports
Cards are drawn by [Satori](https://github.com/vercel/satori), which turns JSX and inline styles into an image. It is not a browser, and supports [a subset of CSS](https://github.com/vercel/satori#css).
- Layout is flexbox. There is no grid, no floats and no `z-index`, and an element with more than one child needs `display: 'flex'`.
- Styles are inline, through the `style` prop. There are no class names or stylesheets.
- `display`, `position` and `overflow` each accept a fixed set of values — `flex`, `block`, `contents`, `none`, `-webkit-box`; `relative`, `absolute`, `static`; `visible`, `hidden`. Anything else stops that page's card from rendering.
- Properties Satori does not implement, such as `float`, `gridTemplateColumns` or `cursor`, are ignored without an error. `calc()` and `zIndex` warn and are ignored too.
Typing a style object as `OgCss` catches unsupported properties while you write.
### Text
Clamp with `display: 'block'` and `lineClamp`, which does nothing on a flex element. Break long tokens with `wordBreak: 'break-word'`, or one package name runs off the card. A text column beside a logo needs `flexShrink: 1` to give way.
```tsx
{title}
```
### Fonts and images
Inter is loaded at weights 400 and 700, so set `fontFamily: 'Inter'` — any other family falls back to it. Pages with non-Latin text get matching Noto fonts added when the site builds; the editor preview only has Inter, so non-Latin text can look different there. Emoji are not supported and draw as an empty box.
Use the `logo` prop as an `img` source, and handle `null` for a site with no logo.
### Imports
A template can import other files inside your project — a shared color, a helper next to it — and those are bundled when the site builds. Packages are not available: an npm package, or a Node builtin like `node:fs`, fails the build and names the import. Inline whatever the card needs.
## When a card fails
- A template that throws, or returns an invalid style value, skips the card for that page. The build log names your file and the error once, and the page is published without an `og:image` tag.
- A template file that is missing or does not compile fails the build.
- A card that takes more than 20 seconds to render is skipped.
## Previewing in the editor
With the configured template open in the Scalar editor, the preview pane draws the card as you type, using your theme and a page from your site, and shows how the link looks on Slack, LinkedIn, iMessage and Discord. It renders in the browser — layout and colors match, but the final PNG is produced when the site builds.
## Learn more
- [Satori's supported CSS](https://github.com/vercel/satori#css)
- [Satori playground](https://og-playground.vercel.app), for trying out layouts
- [The Open Graph protocol](https://ogp.me)
# Ask AI
Ask AI adds an AI-powered assistant to your documentation site. The assistant searches across all your docs content, combines information from multiple pages, and returns a short, accurate answer.
Ask AI is enabled by default for all Scalar Docs projects. No setup required.
## How it works
When a user asks a question, Ask AI searches through all your published documentation. It can combine information from multiple sources to give a complete answer, even when the answer spans several pages.
## AsyncAPI documents
We do not currently support AsyncAPI for Ask AI. [AsyncAPI](../../../asyncapi.md) documents render as API references on your site, but they are not part of the context Ask AI answers from, so it cannot describe your channels or messages.
Need it? Tell us on [GitHub](https://github.com/scalar/scalar/issues/new) or email [support@scalar.com](mailto:support@scalar.com).
## MCP integration
You can connect your docs AI to LLMs like Cursor, Claude Code, Windsurf, and other tools that support Model Context Protocol (MCP). This gives the LLM the full context of your documentation, so it can answer questions about your API and product without you copy-pasting docs into the chat.
Just add /mcp to your Scalar Docs domain.
### Cursor
Add the following to your `.cursor/mcp.json`:
```json
{
"mcpServers": {
"scalar-docs": {
"url": "https:///mcp"
}
}
}
```
### Claude Code
Add the MCP server to your Claude Code configuration:
```sh
claude mcp add --transport http scalar-docs https:///mcp
```
### Other MCP clients
Any MCP-compatible client can connect to your docs AI. Point it to:
```
https:///mcp
```
## Configuration
You can configure Ask AI in the [Scalar Dashboard](https://dashboard.scalar.com). Navigate to your Docs project and open the settings to enable or disable the feature, or to adjust its behavior.
Appearance options — the button, its sidebar placement, the floating widget position, and suggested questions — can also be set via `siteConfig.agent` in `scalar.config.json`. See [site config](site-config.md#ask-ai) for the full list of properties.
## Usage tracking
Team Owners and Admins can see how much each Docs project's Ask AI is used, in messages, tokens, and credits, under **Team → Usage** in the [Scalar Dashboard](https://dashboard.scalar.com). The page shows one month at a time. Tool calls through your docs MCP server are listed separately, under **MCP Servers**. Individual conversations and questions are not shown.
# llms.txt
Every published Scalar Docs site automatically serves `/llms.txt` and `/llms-full.txt` so AI agents and LLMs can read your documentation. These files follow the [llms.txt convention](https://llmstxt.org) and are generated for you. You do not configure or author them.
Hidden pages are left out of both files, matching your sidebar and sitemap.
## llms.txt
`llms.txt` is a structured index of your site. It starts with an H1 for your site title and a short summary as a blockquote, followed by `##` sections that mirror your navigation groups. Each section is a bullet list of links to the pages, pointing at their `.md` URLs, with the page description where one is available.
```markdown
# Your Documentation
> A short summary of your site
## Guides
- [Home](https://your-domain/index.md): The landing page
- [Getting Started](https://your-domain/getting-started/index.md)
## Reference
- [Scalar Galaxy](https://your-domain/api-reference/openapi.json): Explore the Galaxy API
```
The order is stable and follows your navigation, so identical content produces an identical file on every build.
## llms-full.txt
`llms-full.txt` is the full-text companion. It contains the complete Markdown of your pages, concatenated in the same navigation order as `llms.txt`. Use it when an agent needs the entire content of your docs in a single file rather than an index to fetch from.
## Discovery
Both files live at the root of your site:
```
https://your-domain/llms.txt
https://your-domain/llms-full.txt
```
# Personalization
Personalize your published Scalar Docs for signed-in visitors: show relevant navigation and content, display their plan or name, and prefill the API playground. Scalar handles sign-in and calls a **user-info hook**, an HTTPS endpoint you own, to look up the visitor by their verified email address.
Personalization controls visibility, not access. Hidden pages remain reachable by URL, and hidden content remains in the page source. Use [Private Docs](private-docs.md) and access groups to restrict access to an entire site. Do not put confidential content behind a visibility filter.
Personalization has its own project settings page on both public and private sites. **Settings → Privacy** continues to control site access.
## Configure and publish
Add `siteConfig.userInfoHook` to your `scalar.config.json`. The URL must use HTTPS and resolve to a public address; localhost and private network addresses are not supported.
This complete configuration serves a welcome page and an enterprise page. Create the two Markdown files shown below alongside it:
```json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"info": { "title": "Acme Docs" },
"siteConfig": {
"userInfoHook": "https://api.example.com/docs/user-info"
},
"navigation": {
"header": [{ "type": "spacer" }],
"routes": {
"/": {
"type": "page",
"title": "Welcome",
"filepath": "welcome.md"
},
"/enterprise": {
"type": "page",
"title": "Enterprise",
"filepath": "enterprise.md",
"groups": ["enterprise"]
}
}
}
}
```
The `navigation.header` spacer makes the header render without adding a visible link. On a public site with a hook configured, this exposes the sign-in action. Keep the header visible in your site and page layout options.
Replace the endpoint URL with your own. [Publish your project](../deployment/automatic-deployment.md), then open the project in the [Scalar Dashboard](https://dashboard.scalar.com) and go to **Settings → Personalization**.
1. Check that your published endpoint appears. It is read-only here; change it in the configuration and publish again.
2. Click **Generate secret**. Copy the secret immediately: Scalar shows it only once.
3. Store it in your hook server's environment as `SCALAR_USER_INFO_SECRET`. Never put it in your documentation, client-side code, or repository.
The secret belongs to this docs project. Generating or rotating it requires the `team.manage` permission; viewing its status requires `docs.edit`. Removing `userInfoHook` and publishing again stops hook calls.
## Build the hook
Scalar sends a server-to-server request after a visitor signs in. You do not need to build a login flow, configure browser CORS, or pass identity tokens in URLs.
### Request contract
```http
POST /docs/user-info
Content-Type: application/json
User-Agent: Scalar-UserInfo/1
scalar-event: user.info
scalar-signature: t=1770000000,v1=,v1=
```
```json
{
"type": "user.info",
"email": "jane@example.com",
"host": "docs.example.com",
"project": { "uid": "your-project-uid" },
"timestamp": 1770000000
}
```
`email` is verified by Scalar and lowercased. `host` identifies the docs host, and `project.uid` identifies the docs project. `timestamp` is Unix time in seconds and matches the signed header timestamp.
**Verify the signature before looking up or returning user data.** Compute HMAC-SHA256 over `.` using the complete signing secret, including its `whsec_` prefix, as the UTF-8 key. Compare the hexadecimal digest with any `v1` signature using a constant-time comparison. Preserve the raw body bytes: parsing and re-serializing JSON changes the signed payload. Reject timestamps more than 300 seconds in the past or future.
### Working Node.js example
Save this as `user-info.mjs`. It uses only Node.js built-ins. Set `DOCS_DEMO_EMAIL` to an email address you can sign in with. The example returns demo profile data for that address and no context for everyone else. Replace the demo lookup with your customer database lookup when adopting it.
```js
import { createHmac, timingSafeEqual } from 'node:crypto'
import { createServer } from 'node:http'
const secret = process.env.SCALAR_USER_INFO_SECRET
const demoEmail = process.env.DOCS_DEMO_EMAIL?.toLowerCase()
if (!secret || !demoEmail) {
throw new Error('Set SCALAR_USER_INFO_SECRET and DOCS_DEMO_EMAIL')
}
const verifySignature = (header, body) => {
if (typeof header !== 'string') return null
const parts = header.split(',').map((part) => part.trim())
const timestamp = parts.find((part) => part.startsWith('t='))?.slice(2)
if (!timestamp || !/^\d+$/.test(timestamp)) return null
const seconds = Number(timestamp)
if (!Number.isSafeInteger(seconds)) return null
if (Math.abs(Date.now() / 1000 - seconds) > 300) return null
const expected = createHmac('sha256', secret)
.update(`${timestamp}.`)
.update(body)
.digest()
const valid = parts.some((part) => {
if (!/^v1=[a-f0-9]{64}$/.test(part)) return false
return timingSafeEqual(expected, Buffer.from(part.slice(3), 'hex'))
})
return valid ? seconds : null
}
createServer(async (request, response) => {
response.setHeader('Cache-Control', 'no-store')
if (request.method !== 'POST' || request.url !== '/docs/user-info') {
response.writeHead(404).end()
return
}
try {
const chunks = []
let size = 0
for await (const chunk of request) {
size += chunk.length
if (size > 64 * 1024) {
response.writeHead(413).end()
return
}
chunks.push(chunk)
}
const body = Buffer.concat(chunks)
const timestamp = verifySignature(request.headers['scalar-signature'], body)
if (timestamp === null) {
response.writeHead(401).end()
return
}
const lookup = JSON.parse(body.toString('utf8'))
if (
request.headers['scalar-event'] !== 'user.info' ||
lookup?.type !== 'user.info' ||
lookup.timestamp !== timestamp ||
typeof lookup.email !== 'string' ||
typeof lookup.host !== 'string' ||
typeof lookup.project?.uid !== 'string'
) {
response.writeHead(400).end()
return
}
if (lookup.email !== demoEmail) {
response.writeHead(204).end()
return
}
response.writeHead(200, { 'Content-Type': 'application/json' })
response.end(
JSON.stringify({
expiresAt: Math.floor(Date.now() / 1000) + 300,
groups: ['enterprise'],
content: { firstName: 'Jane', plan: 'Enterprise' },
apiPlaygroundInputs: { server: { subdomain: 'acme' } },
}),
)
} catch {
response.writeHead(400).end()
}
}).listen(3000)
```
Set both environment variables in your hosting provider's secret settings, then run `node user-info.mjs`. Deploy behind HTTPS so the published URL forwards `/docs/user-info` to this server on port 3000. The local HTTP listener alone cannot receive Scalar's hook calls. Keep the signing secret on the server.
### Response contract
Return a `200` response containing the user-info object directly, without a `user` wrapper. All fields are optional; unknown fields are ignored.
| Field | Type | Behavior |
| --------------------- | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `expiresAt` | Positive integer | Unix seconds, not milliseconds. Hosting caches until this time, capped at 15 minutes. If omitted, the cache lasts 15 minutes. An already expired response supplies no context. |
| `groups` | Array of strings | Up to 100 case-sensitive group names, each 1–64 characters, starting with a letter or digit and containing only letters, digits, `_`, `.`, `:`, or `-`. Merged with the access-group slugs the visitor matches. |
| `content` | Object | Up to 100 top-level keys, each 1–64 characters. `UserValue` renders string and number values; other values use its fallback. |
| `apiPlaygroundInputs` | Object of string maps | Optional `header`, `query`, `cookie`, and `server` maps. Keys are 1–200 characters; values are strings of at most 4,096 characters. See the supported prefills below. |
Return `204` or `404` for an unknown visitor. Scalar treats these as no context without logging an error. Other non-2xx responses, invalid payloads, responses over 64 KB, and requests taking more than five seconds also supply no hook context. They do not prevent sign-in or grant access to a private site.
Hosting caches context per project and email. The docs client loads user context once per page load; an open page does not automatically refresh at `expiresAt`. Reload after the cache expires to see updated data.
## Personalize content
Create `welcome.md` with this content:
```markdown
# Welcome
Hello, :user[firstName]{fallback="visitor"}. Your plan is :user[plan]{fallback="Free"}.
:::visible{groups="enterprise"}
Your enterprise workspace includes priority support.
:::
:::visible{groups="enterprise" not}
Contact us to learn about the enterprise plan.
:::
```
Create `enterprise.md`:
```markdown
# Enterprise
Learn how to get the most from your enterprise workspace.
```
Publish these files, then open your site while signed out. You should see the fallback values and the enterprise contact message. Sign in with `DOCS_DEMO_EMAIL`: after the hook succeeds, the welcome page shows Jane and Enterprise, the support block appears, and the Enterprise navigation entry becomes visible. Signing out restores the anonymous view.
### MDX elements
In MDX, use the corresponding elements directly:
```mdx
Hello, .
Your enterprise workspace includes priority support.
Contact us to learn about the enterprise plan.
```
`Visible` matches any of the listed groups. Use `groups="enterprise,admin"` to accept either; `not` shows the block to visitors who match none, including anonymous visitors. `UserValue` reads one top-level `content` key and inserts text, never HTML. Its `name` may contain letters, digits, underscores, dots, or hyphens, up to 64 characters. A dot is part of the key, not a nested property lookup. Its fallback defaults to an empty string.
## Filter navigation
Add `groups` to a page, link, or OpenAPI navigation entry at the top level or inside a group, to a nested group inside `children`, or to a header link. Top-level route sections (`type: "group"` directly under `navigation.routes`) do not support `groups`; put a filtered group inside their `children` instead. An entry is visible if the visitor has at least one matching group. Entries without groups (or with an empty list) remain visible to everyone. Group names are case-sensitive: `Enterprise` and `enterprise` differ.
For example, add this entry under `navigation.routes` to show a nested Customer resources group to enterprise visitors or administrators:
```json
{
"/resources": {
"type": "group",
"title": "Resources",
"children": {
"/customer": {
"type": "group",
"title": "Customer resources",
"mode": "folder",
"groups": ["enterprise", "admin"],
"children": {
"/support": {
"type": "link",
"title": "Contact support",
"url": "https://example.com/support"
}
}
}
}
}
}
```
You can also set groups in page frontmatter:
```markdown
---
groups: [enterprise, admin]
---
# Customer resources
```
Filtering a parent group hides its children in navigation too. These filters do not protect the pages' URLs. Hook groups do not need to be created as dashboard access groups, and returning an access-group name from the hook does not grant access to a private site.
## Prefill the API playground
Return `apiPlaygroundInputs` to supply defaults for declared API security schemes and server variables:
```json
{
"apiPlaygroundInputs": {
"header": {
"Authorization": "Bearer visitor-scoped-token",
"X-API-Key": "visitor-api-key"
},
"query": { "api_key": "visitor-api-key" },
"cookie": { "api_key": "visitor-api-key" },
"server": { "subdomain": "acme" }
}
}
```
For an `apiKey` security scheme, Scalar matches the key's location (`header`, `query`, or `cookie`) and declared name, such as `X-API-Key`. HTTP bearer schemes use the token from the `Authorization: Bearer …` header. Server values match declared server variable names, such as `subdomain`. These defaults sit underneath the visitor's manual edits.
The current implementation does not prefill arbitrary operation parameters, request bodies, HTTP Basic credentials, or OAuth flows. Undeclared inputs do not create new security schemes or server variables.
Playground credentials reach the visitor's browser. Return only short-lived, narrowly scoped credentials belonging to that visitor. Do not return a privileged application session or place credentials in `content`.
## Public and private sites
On a **public site**, configuring a hook enables sign-in for personalization. Visitors can continue reading anonymously; signing in does not turn public pages into protected pages. Use a visible header, as in the configuration above, to expose the sign-in action.
On a **private site**, Scalar checks the existing site access rules before asking the hook for context. Workspace membership and configured access groups still determine who gets in. The hook enriches an admitted visitor; it cannot admit someone or deny their existing site access. Matching access-group slugs are included alongside groups returned by the hook.
Scalar uses its existing magic-link, Google, Microsoft, or configured SSO sign-in flow and a first-party HTTP-only cookie. The docs client requests `/_scalar/me` on your docs origin (under the project's subpath for multi-project domains). Anonymous visitors receive `{ "user": null }`.
## Rotate the signing secret
In **Settings → Personalization**, rotate the secret and copy the newly displayed value into your hook server's secret settings. Redeploy or restart the hook so it uses the new value.
During normal rotation, Scalar signs with both the new secret and the previous secret for a 24-hour grace window. The verifier above accepts any matching `v1` signature, so the old deployment continues working while you update it. Complete the update before the grace window ends.
If you revoke the previous secret during rotation, it stops being accepted immediately. Update the hook promptly; verification against the revoked secret fails and personalization has no hook context until the new secret is installed. Previously cached context can remain until its expiry.
## Current limitations
- Local preview does not load visitor identity. Test sign-in and hook calls on a published site.
- Visibility filters run in the browser. Hidden navigation entries remain reachable by URL, and `Visible` content remains in HTML source. `Visible` blocks are omitted from plain Markdown exports, but this is not a confidentiality guarantee.
- Page groups are not enforced server-side, including on private sites. Keep content with different access requirements in separately protected sites.
- Search and sitemaps are not group-aware. Do not rely on groups to hide content from discovery.
- Groups do not filter individual OpenAPI operations or schema properties.
- Use Markdown directives or MDX for `Visible` and `UserValue`; the visual editor does not currently provide menus for these elements.
- Hook errors remove hook-provided context, not the visitor's sign-in or existing site access. Design useful anonymous and fallback content.
# Private Docs
This guide shows you how to make a Docs site private and use access groups to choose who can view it. You can set this up in the dashboard and editor, or in your `scalar.config.json`.
Make sure you have created a Scalar Account & are logged in ([see create account guide](../../registry/getting-started.md#create-your-scalar-account))
## Create your first access group
Access groups decide who outside your team can view a private site. Creating one needs the Pro plan or above.
In the [dashboard](https://dashboard.scalar.com), open **Settings** and go to **Configuration → Access Groups**. Click **New Access Group**, give it a name and a slug, then click **Create Access Group**.
Now that you have an access group, you can allow a whole email domain, specific email addresses, or both.
### Allow an email domain
Under **Email Domain**, type a domain like `example.com` and click **Allow**. Anyone with an address at that domain can sign in.
### Allow specific email addresses
Under **Specific Email Addresses**, type an email address and click **Add**.
## Make your docs private
Open your [Docs](../getting-started.md) project in the editor and go to **Settings → Privacy**. Under **Access control**:
1. Turn on **Private site**. Visitors now have to sign in, and members of your team always have access.
2. Optionally, pick a **Login portal** to brand the sign-in page. Without one, visitors see the default sign-in page.
3. Under **Access groups**, add the groups that should be able to view the site.
Save and publish your changes for them to take effect. If you delete an access group later, its members lose access immediately.
## Configure in scalar.config.json
The Private Docs toggle, access groups and login portal are also stored in your `scalar.config.json`, so you can set them in your repository:
```json
{
"siteConfig": {
"isPrivate": true,
"accessGroups": ["partners"]
}
}
```
See [Access Control](site-config.md#access-control) for every property.
# Migrate from Docs 1.0
With Docs 2.0 we've completely started from scratch. We tried to stick to the patterns we already had, so the way you set it up is not too different.
**TL;DR**
Migrate your scalar.config.json with: `npx @scalar/cli project upgrade`
## New Features in Docs 2.0
* MDX support with custom components
* `[relative Markdown paths](../your-other-file.md)`
* Per-operation page rendering for API references (huge performance boost for large OpenAPI documents)
* Configurable navigation structures: nested, grouped, or flattened
* Full `` customization (meta tags, scripts, stylesheets)
* Local file imports for CSS, scripts, and static assets
* Local OpenAPI file references with `$ref` resolution
* Subpath deployment with unified cross-project search
* "Copy as Markdown"
* … and so much more, it's crazy.
## How do I know whether I use Docs 1.0?
If you created a project before February 2026, you probably use Docs 1.0:
```json
// scalar.config.json (Docs 1.0)
{
"$schema": "https://cdn.scalar.com/schema/scalar-config.json",
"siteConfig": {
// …
},
"guides": [
// …
],
"references": [
// …
],
}
```
For Docs 2.0 we still use the `scalar.config.json`, but the structure changed a bit:
```json
// scalar.config.json (Docs 2.0)
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"info": {
// …
},
"siteConfig": {
// …
},
"navigation": {
"routes": {
// …
}
}
}
```
## Do you have to switch to 2.0?
Actually, under the hood, you’re using Docs Version 2 already.
If you want to actually use new features and upgrade your configuration file use the CLI to upgrade:
```bash
npx @scalar/cli project upgrade
```
Check how your documentation looks with:
```bash
npx @scalar/cli project preview
```
If it's good, commit and push the upgraded configuration to your repository – done!
# Automatic Deployment
Docs can automatically publish your documentation whenever changes are merged into your default branch (usually `main`).
Enable automatic deployment and configure which branch triggers it in the [Scalar Dashboard](https://dashboard.scalar.com) under your project settings. Every time you merge changes into your default branch, your documentation will be automatically published.
The setting is stored in your `scalar.config.json` as `publishOnMerge`, so you can also turn it on or off in your repository:
```json
{
"publishOnMerge": true
}
```
See [Publishing](../configuration/scalar.config.json.md#publishing) for the related preview settings.
If your Docs project references an API document from the Registry, updating that Registry document also triggers the Docs project to publish again. Once your document is in the Registry, your documentation stays up to date automatically.
## Other Deployment Options
Looking for more control over your deployment process?
- [GitHub Actions](github-actions.md) - Trigger deployments based on specific events
- [Scalar CLI](cli.md) - Deploy from your terminal or any CI/CD environment
# CLI
Publish your Docs project using the Scalar CLI. The CLI uploads your project configuration and content to Scalar's platform, making your documentation available at a custom domain.
## Deployment modes
`scalar project publish` supports two ways to deploy:
- **Default:** The CLI uploads your project configuration and content from your local machine to Scalar. What you have on disk is what gets deployed.
- **With `--github`:** Use only when your Docs project is connected to a GitHub repository. Scalar pulls the files from GitHub and deploys that. Local changes are ignored. Use this to trigger a deploy from the linked repository.
## Installation
Install the [Scalar CLI](../../cli/getting-started.md) globally or use it via npx. The CLI requires Node.js 24 or later.
```bash
npm install -g @scalar/cli
```
Or use npx without installation:
```bash
npx @scalar/cli project publish --slug your-docs
```
## Authentication
Authenticate with the Scalar platform before publishing:
```bash
scalar auth login
```
This opens a browser to sign in. In CI or on a remote machine, use a personal token instead. Create one in the [dashboard](https://dashboard.scalar.com/account) under **Account > API Keys**:
```bash
scalar auth login --token your-personal-token
```
You can also set `SCALAR_API_KEY` and run `scalar auth login`. In CI, always use a token: without one, the CLI waits up to three minutes for a browser sign-in and then fails.
Verify your current authentication status:
```bash
scalar auth whoami
```
## Project Setup
### Initialize Configuration
Create a `scalar.config.json` file in your project root:
```bash
scalar project init
```
This command prompts for a subdomain and creates the configuration file.
### Create Project
Create a new project on the Scalar platform:
```bash
scalar project create --name "My Documentation" --slug your-docs
```
| Option | Type | Required | Description |
| -------- | -------- | -------- | ------------------------------- |
| `--name` | `string` | Yes, outside an interactive terminal | Display name for your project |
| `--slug` | `string` | No | URL-friendly project identifier |
## Local Preview
Preview your documentation locally before publishing:
```bash
scalar project preview
```
## Preview Deployments
Publish in preview mode (e.g. for pull requests) without going live:
```bash
scalar project publish --slug your-docs --preview
```
## Publishing
### Publish from local files
Publish your project by uploading it directly from your machine. Pass the project slug, which you can find with `scalar project list`:
```bash
scalar project publish --slug your-docs
```
If your config file is not in the current folder, point to it with `--config`:
```bash
scalar project publish --slug your-docs --config path/to/scalar.config.json
```
### Publish from GitHub
If your project is connected to a GitHub repository, you can deploy from the remote repo instead. Scalar pulls the files from GitHub; local changes are ignored.
```bash
scalar project publish --slug your-docs --github
```
### Options
| Option | Type | Required | Description |
| ----------- | --------- | -------- | ------------------------------------------------------------------------------------------------------- |
| `--slug` | `string` | Yes | Project slug. Find it with `scalar project list`. |
| `--config` | `string` | No | Path to your scalar.config.json file |
| `--preview` | `boolean` | No | Publish in preview mode (do not go live) |
| `--github` | `boolean` | No | Publish from the project's linked GitHub repository (Scalar pulls from GitHub; local files are ignored) |
Use `project publish` for ad-hoc or local-first workflows. Use `project publish --github` when the project is connected to GitHub and you want the deployment to reflect the remote repository.
Your documentation will be available at `https://your-subdomain.apidocumentation.com`.
## Rollback
If a deployment introduced a problem, you can roll the live deployment back to a previously deployed build. List recent production deployments to find the build you want, then roll back to the previous build (or pass `--to ` to target a specific one).
```bash
# See recent production deployments
scalar project deployments list --slug your-docs
# Roll back to the previous build (or pass --to )
scalar project rollback --slug your-docs
```
# Publish Scalar Projects using GitHub Actions
You can add a [GitHub Actions workflow](https://docs.github.com/en/actions/get-started/quickstart) to automatically publish your Scalar projects.
## Basic Workflow
Here's a simple workflow that publishes a Scalar project:
```yaml
# .github/workflows/publish-scalar-project.yml
name: Publish Scalar Project
on:
push:
branches:
- main
jobs:
publish-project:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Use Node.js
uses: actions/setup-node@v6
with:
node-version: 24
- name: Log in to Scalar
run: npx @scalar/cli auth login --token ${{ secrets.SCALAR_API_KEY }}
- name: Publish Project
run: npx @scalar/cli project publish --slug your-docs
```
## Environment-Based Deployment
For different environments:
```yaml
# .github/workflows/publish-scalar-project.yml
name: Publish Scalar Project
on:
push:
branches:
- main
- development
jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Use Node.js
uses: actions/setup-node@v6
with:
node-version: 24
- name: Install Scalar CLI
run: npm install -g @scalar/cli
- name: Authenticate Scalar
env:
SCALAR_API_KEY: ${{ secrets.SCALAR_API_KEY }}
run: scalar auth login
- name: Set project slug
if: github.ref == 'refs/heads/main'
run: echo "PROJECT_SLUG=production-project" >> $GITHUB_ENV
- name: Set development slug
if: github.ref == 'refs/heads/development'
run: echo "PROJECT_SLUG=development-project" >> $GITHUB_ENV
- name: Publish Project
run: scalar project publish --slug "$PROJECT_SLUG"
```
## Secrets
Create a personal token in the [dashboard](https://dashboard.scalar.com/account) under **Account > API Keys**, then add it to your GitHub repository as a secret named `SCALAR_API_KEY`. The Scalar CLI requires Node.js 24 or later, so keep the `setup-node` step in your workflow.
# Preview Deployments
Preview deployments allow you to see how your documentation changes will look before merging them into your main branch. When you open a pull request, Docs automatically creates a preview deployment and can post a comment with a link to preview your changes.
## Enable in the Dashboard
Configure preview deployments and pull request comments in the [Scalar Dashboard](https://dashboard.scalar.com) under your project settings. You can:
- Enable preview deployments for every pull request
- Enable automatic comments on pull requests with a direct link to the preview
### Configure in scalar.config.json
These toggles are stored in your `scalar.config.json` as `publishPreviews` and `pullRequestComments`, so you can also set them in your repository:
```json
{
"publishPreviews": true,
"pullRequestComments": true
}
```
See [Publishing](../configuration/scalar.config.json.md#publishing) for details.
### GitHub Pull Request Comments for Preview Deployments
When enabled in the Dashboard, Scalar posts a comment on each pull request with a direct link to the preview deployment:

## CLI
If your Docs project is not connected to your GitHub repository, use the CLI publish in preview mode (e.g. for pull requests) without going live:
```bash
npx @scalar/cli project publish --slug your-docs --preview
```
## Other Deployment Options
Looking for more control over your deployment process?
- [Automatic Deployment](automatic-deployment.md) - Automatically publish when changes are merged
- [GitHub Actions](github-actions.md) - Trigger deployments based on specific events
- [CLI](cli.md) - Deploy from your terminal or any CI/CD environment
# Build Failures
When a deployment fails, use these tools to diagnose the issue:
```bash
# Validate your configuration
scalar project check-config
# Run a local preview to surface warnings
scalar project preview
```
Check the [Scalar Dashboard](https://dashboard.scalar.com/) for detailed build logs.
## Common Issues
### Subdomain Conflicts
If your build fails silently, verify your subdomain is not already in use.
Fun fact: Subdomain conflicts do not currently produce an explicit error. (I know, I know… We'll improve this. So sorry.)
### Need Help?
Contact [support@scalar.com](mailto:support@scalar.com), we'll help you swiftly.
# Assets
The `assetsDir` configuration allows you to specify a folder containing custom assets such as images, scripts, stylesheets, and other static files. These assets are served globally from the root path of your documentation site, making them accessible from any page.
**Example**
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"assetsDir": "docs/assets",
"navigation": {
"routes": {
// ...
}
}
}
```
## Configuration
The `assetsDir` property specifies a relative path to your assets folder from the location of your `scalar.config.json` file.
### Properties
| Property | Type | Required | Description |
| ----------- | -------- | -------- | -------------------------------------------------------------- |
| `assetsDir` | `string` | No | Relative path to the assets folder from the configuration root |
## Referencing Assets
Once you've configured `assetsDir`, assets in that folder are served from the root path of your site. This means a file at `docs/assets/picture.png` will be accessible at `/picture.png`.
### In Markdown Files
You can reference assets in your markdown files using either absolute paths from the site root or relative paths:
**Absolute URLs** (root-relative):
```markdown


[Download PDF](/documentation.pdf)
```
**Relative paths**:
```markdown


```
- Absolute paths (`/path/to/file.png`) are recommended when you want paths that work consistently regardless of the markdown file's location
- Relative paths (`../assets/file.png`) are useful when you want paths relative to the current markdown file's location
### In siteConfig.head
Assets can also be referenced in the `siteConfig.head` configuration for scripts, stylesheets, and other head elements:
```json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"assetsDir": "docs/assets",
"siteConfig": {
"head": {
"scripts": [
{
"path": "docs/assets/analytics.js"
}
],
"styles": [
{
"path": "docs/assets/custom.css"
}
],
"links": [
{
"rel": "icon",
"href": "/favicon.png"
}
]
}
}
}
```
Note that when referencing assets in `siteConfig.head`:
- For `scripts` and `styles`, use the full path relative to your configuration root (e.g., `docs/assets/script.js`)
- For `links` like favicons, use the root-relative path (e.g., `/favicon.png`)
## Complete Example
Here's a complete example showing how to configure assets and use them throughout your site:
```json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"assetsDir": "docs/assets",
"siteConfig": {
"head": {
"scripts": [
{
"path": "docs/assets/landing.js",
"tagPosition": "head"
},
{
"path": "docs/assets/analytics.js",
"tagPosition": "bodyClose"
}
],
"styles": [
{
"path": "docs/assets/styles.css"
}
],
"links": [
{
"rel": "icon",
"href": "/favicon.png"
}
]
}
},
"navigation": {
"routes": {
"/": {
"type": "page",
"title": "Introduction",
"filepath": "docs/introduction.md"
}
}
}
}
```
In your Markdown files, you can then reference these assets:
```markdown
# Introduction

Welcome to our documentation. Check out our [API Client](/api-client-static.svg) for more details.
```
# HTML/CSS/JS
Docs supports custom HTML, CSS, and JavaScript to give you full control over your documentation pages. You can write raw HTML directly in Markdown files, add custom styles inline or via external stylesheets, and include JavaScript for interactivity.
## Writing HTML Pages
You can write raw HTML directly in your Markdown (`.md`) files. This is useful for creating custom landing pages, marketing pages, or any page that needs custom layout and styling.
**Example**
Create a Markdown file with HTML content:
```html
```
### Inline Styles
Add a `
```
### Using Scalar CSS Variables
Scalar provides CSS variables for consistent theming. Use these in your custom styles:
**Colors**
Defined in [theme presets](https://github.com/scalar/scalar/blob/main/packages/themes/src/presets/default.css)
| Variable | Description |
| ----------------------- | -------------------- |
| `--scalar-color-1` | Primary text color |
| `--scalar-color-2` | Secondary text color |
| `--scalar-color-3` | Tertiary text color |
| `--scalar-color-accent` | Accent/brand color |
| `--scalar-background-1` | Primary background |
| `--scalar-background-2` | Secondary background |
| `--scalar-background-3` | Tertiary background |
| `--scalar-border-color` | Border color |
**Typography and Sizing**
Defined in [variables.css](https://github.com/scalar/scalar/blob/main/packages/themes/src/base/variables.css)
| Variable | Description |
| ---------------------- | -------------------------------- |
| `--scalar-font` | Default font family |
| `--scalar-font-code` | Monospace/code font family |
| `--scalar-radius` | Default border radius (3px) |
| `--scalar-radius-md` | Default radius, capped (3px) |
| `--scalar-radius-lg` | Large border radius (6px) |
| `--scalar-radius-xl` | Extra large border radius (8px) |
| `--scalar-radius-2xl` | 2x large border radius (12px) |
| `--scalar-radius-3xl` | 3x large border radius (16px) |
| `--scalar-radius-full` | Fully rounded pills and circles |
| `--scalar-radius-max` | Ceiling for container corners |
| `--scalar-paragraph` | Paragraph font size (16px) |
| `--scalar-small` | Small text font size (14px) |
**Border radius**
Every border radius derives from `--scalar-radius`, so overriding that one variable rescales the whole
interface. Set it to `0` for square corners throughout.
```css
:root {
--scalar-radius: 0; /* everything squares off, pills and circles included */
}
```
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 (on `.scalar-app`, for instance) moves the base
without moving any of the radii derived from it. Individual tokens can still be overridden on their own
if you want to break the ratio.
Corners on anything that holds content stop growing at `--scalar-radius-max`, which defaults to `20px`.
Without it a large radius curves a dropdown or a code block so hard that it swallows what is inside.
Pills and circles (`--scalar-radius-full`) are deliberately exempt.
### Using Scalar Components
You can use Scalar's built-in components in your HTML:
```html
My Section Title
```
### Dark Mode Support
Use CSS classes to show different content based on the color mode:
```html
```
### Hiding Default Page Elements
You can hide the table of contents via page configuration in `scalar.config.json`:
```json
{
"navigation": {
"routes": {
"/my-landing-page": {
"type": "page",
"filepath": "documentation/landing.md",
"layout": {
// We don't want the table of contents here:
"toc": false
}
}
}
}
}
```
## Site-Wide Head Configuration
The `siteConfig.head` configuration allows you to inject custom HTML elements into the `` of your documentation pages. This enables you to add custom stylesheets, JavaScript files, meta tags for SEO and social sharing, and link elements like favicons.
All head configuration is done within the `siteConfig.head` object in your `scalar.config.json` file.
**Example**
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"siteConfig": {
"head": {
"scripts": [
{
"path": "documentation/assets/analytics.js"
}
],
"styles": [
{
"path": "documentation/assets/styles.css"
}
],
"meta": [
{
"name": "description",
"content": "Documentation for my API"
}
],
"links": [
{
"rel": "icon",
"href": "/favicon.png"
}
]
}
}
}
```
## Scripts
The `scripts` array allows you to include custom JavaScript files in your documentation. Scripts can be injected into the `` or at the end of the `` tag, depending on your needs.
### Example
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"siteConfig": {
"head": {
"scripts": [
{
"path": "documentation/assets/analytics.js",
"tagPosition": "bodyClose"
}
]
}
}
}
```
### Properties
| Property | Type | Required | Description |
| ------------- | ------------------------------------- | -------- | ----------------------------------------------------------------- |
| `path` | `string` | Yes | Relative path to the JavaScript file from your configuration root |
| `tagPosition` | `"head" \| "bodyOpen" \| "bodyClose"` | No | Where to inject the script tag (defaults to `"head"`) |
### Tag Position
- `head`: Scripts are injected into the `` element. Use this for scripts that need to load early, such as analytics initialization or critical functionality.
- `bodyOpen`: Scripts are injected immediately after the opening `` tag. Use this for scripts that need to access the DOM as soon as possible but do not need to block page rendering.
- `bodyClose`: Scripts are injected just before the closing `` tag. Use this for non-critical scripts or analytics that should not block page rendering.
## Styles
The `styles` array allows you to include custom CSS files to customize the appearance of your documentation site.
### Example
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"siteConfig": {
"head": {
"styles": [
{
"path": "documentation/assets/styles.css"
}
]
}
}
}
```
### Properties
| Property | Type | Required | Description |
| ------------- | ------------------------------------- | -------- | ---------------------------------------------------------- |
| `path` | `string` | Yes | Relative path to the CSS file from your configuration root |
| `tagPosition` | `"head" \| "bodyOpen" \| "bodyClose"` | No | Where to inject the style tag (defaults to `"head"`) |
## Meta Tags
The `meta` array allows you to add meta tags for SEO, social sharing (Open Graph, Twitter Cards), and other metadata. Meta tags can be provided as an array of objects or as a key-value object.
### Array Format
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"siteConfig": {
"head": {
"meta": [
{
"name": "description",
"content": "Documentation for my API"
},
{
"property": "og:title",
"content": "My API Documentation"
},
{
"property": "og:image",
"content": "https://example.com/og-image.png"
}
]
}
}
}
```
### Properties
| Property | Type | Required | Description |
| ---------- | -------- | ----------- | ------------------------------------------------------- |
| `name` | `string` | Conditional | The meta `name` attribute (use for standard meta tags) |
| `property` | `string` | Conditional | The meta `property` attribute (use for Open Graph tags) |
| `content` | `string` | Yes | The meta tag content value |
### Common Meta Tags
**SEO Meta Tags**
```json
"meta": [
{
"name": "description",
"content": "Comprehensive API documentation"
},
{
"name": "keywords",
"content": "API, documentation, REST"
}
]
```
**Open Graph Tags (for social sharing)**
```json
"meta": [
{
"property": "og:title",
"content": "My API Documentation"
},
{
"property": "og:description",
"content": "Comprehensive API documentation"
},
{
"property": "og:image",
"content": "https://example.com/og-image.png"
},
{
"property": "og:type",
"content": "website"
}
]
```
**Twitter Card Tags**
```json
"meta": [
{
"name": "twitter:card",
"content": "summary_large_image"
},
{
"name": "twitter:title",
"content": "My API Documentation"
},
{
"name": "twitter:image",
"content": "https://example.com/twitter-image.png"
}
]
```
## Links
The `links` array allows you to add link elements to the ``, commonly used for favicons, preconnect hints, and other resource links.
### Example
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"siteConfig": {
"head": {
"links": [
{
"rel": "icon",
"type": "image/png",
"href": "/favicon.png"
},
{
"rel": "preconnect",
"href": "https://fonts.googleapis.com"
}
]
}
}
}
```
### Properties
| Property | Type | Required | Description |
| -------- | -------- | -------- | ---------------------------------------------------------------- |
| `rel` | `string` | Yes | The relationship type (e.g., `icon`, `preconnect`, `stylesheet`) |
| `href` | `string` | Yes | The URL or path to the resource |
| `type` | `string` | No | The MIME type of the resource (e.g., `image/png`) |
### Common Link Types
**Favicon**
```json
"links": [
{
"rel": "icon",
"type": "image/png",
"href": "/favicon.png"
}
]
```
**Preconnect (for performance optimization)**
```json
"links": [
{
"rel": "preconnect",
"href": "https://fonts.googleapis.com"
},
{
"rel": "preconnect",
"href": "https://fonts.gstatic.com",
"crossorigin": "anonymous"
}
]
```
**Canonical URL**
```json
"links": [
{
"rel": "canonical",
"href": "https://docs.example.com"
}
]
```
## Common Use Cases
### Analytics Integration
Add analytics scripts like Fathom, Google Analytics, or other tracking tools:
```json
"scripts": [
{
"path": "documentation/assets/analytics.js",
"tagPosition": "bodyClose"
}
]
```
### Custom Branding and Styling
Override default styles to match your brand:
```json
"styles": [
{
"path": "documentation/assets/style.css"
}
]
```
### SEO Optimization
Add comprehensive meta tags for better search engine visibility and social sharing:
```json
"meta": [
{
"name": "description",
"content": "Your comprehensive API documentation"
},
{
"property": "og:title",
"content": "API Documentation"
},
{
"property": "og:description",
"content": "Your comprehensive API documentation"
},
{
"property": "og:image",
"content": "https://example.com/social-preview.png"
}
]
```
### Favicon Configuration
Add custom favicons for your documentation site:
```json
"links": [
{
"rel": "icon",
"type": "image/png",
"href": "/favicon-32x32.png",
"sizes": "32x32"
},
{
"rel": "icon",
"type": "image/png",
"href": "/favicon-16x16.png",
"sizes": "16x16"
},
{
"rel": "apple-touch-icon",
"href": "/apple-touch-icon.png"
}
]
```
## Path References
When referencing files in `siteConfig.head`:
- For `scripts` and `styles`: Use the full path relative to your configuration root (e.g., `documentation/assets/script.js`)
- For `links` like favicons: Use root-relative paths (e.g., `/favicon.png`) since these files should be in your `assetsDir` and are served from the site root
Make sure your asset files are located in the directory specified by `assetsDir` or use absolute paths from your configuration root.
# MDX
MDX lets you use JavaScript and JSX components inside your Markdown files.
## Prerequisites
* Use `.mdx` instead of `.md` for the file extension.
## Configuration
Reference MDX files the same way as Markdown files:
```json
// scalar.config.json
{
"$schema": "https://registry.scalar.com/@scalar/schemas/config",
"scalar": "2.0.0",
"navigation": {
"routes": {
"/example": {
"title": "Example",
"type": "page",
"filepath": "docs/content/example.mdx" // .mdx extension
}
}
}
}
```
## Frontmatter
Add metadata at the top of your MDX files:
```markdown
---
title: "Page Title"
description: "Page description for SEO"
---
# Content
This is the content of the page.
```
## Importing Components
Import and use other MDX files as components:
```markdown
// Import MDX from other files
import Intro from './intro.mdx'
# Example
This is **Markdown**.
```
And this is how the other
```markdown
# Introduction
This MDX file serves as an imported component in another MDX document.
You can include any Markdown or JSX content here to be reused elsewhere.
```
## JSX Elements
Use JSX directly in your content:
```markdown
Custom styled content
```
Custom Styles
Interactive elements work too:
```markdown
```
Click me
## Expressions
Embed JavaScript expressions using curly braces:
**Code**
```markdown
The current year is {new Date().getFullYear()}.
```
**Preview**
The current year is 2026.
# GitHub
Docs connects to GitHub to read your files, open pull requests, and publish when you merge. Here's what that connection can and can't do.
## Setup
1. **Install the Scalar GitHub App.** You pick which repositories it can access. Change the selection any time.
2. **Link your GitHub user.** This attributes commits and pull requests to you.
Access is always limited to the repositories you pick. Nothing else.
## Switch repositories
For a project already connected to GitHub or Bitbucket, you can switch to another repository on either provider without disconnecting first.
The destination repository must already contain your documentation. Switching does not copy files or open a pull request to move them, so move your documentation to the destination yourself before switching.
1. Open your documentation project in the [Scalar Dashboard](https://dashboard.scalar.com) and go to **Settings → Git Sync**.
2. Click **Switch repository** beside the connected repository.
3. Choose GitHub or Bitbucket, authorize access if prompted, and select the repository containing your docs. For GitHub, make sure the Scalar GitHub App has access to that repository.
4. Review the confirmation, which names the repository you are leaving and the destination, then click **Switch**.
The editor reloads the destination repository, replacing the contents of the docs project. Future edits are committed to the new repository. Files in the previous repository stay as they are, and your live site keeps serving its current build until the next publish.
Scalar uses the destination repository's default branch and looks for a `scalar.config.*` file in the current configuration directory, the repository root, and `scalar-docs/`, in that order. If none is found, it keeps the project's current configuration path. Check the configuration and **Tracked branch** in Git Sync before publishing.
## What we can access
Only in the repositories you select:
- **Contents** — read your files and write changes through commits and pull requests.
- **Pull requests** — open and update pull requests.
- **Metadata** — basic repository info (required for every GitHub App).
## What we can't access
- Repositories you didn't select.
- Your other code across your account or organization.
- Repository settings, collaborators, or branch protection.
## "Act on your behalf"
GitHub shows this line for any app that can write to a repository, because your commits and pull requests are attributed to you. It's about attribution, not broad access. See GitHub's own [explanation](https://docs.github.com/en/apps/using-github-apps/authorizing-github-apps#about-github-apps-acting-on-your-behalf).
## Manage access
Change repositories or revoke access from GitHub under **Settings → Applications → Installed GitHub Apps**, or from the [Scalar Dashboard](https://dashboard.scalar.com). Removing a repository cuts off access to it right away.
# Markdown Support
We support all standard Markdown features, based on GitHub-flavored Markdown (GFM).
## Headings
Use one to six `#` characters to create headings from level one through six.
```md
# Heading 1
## Heading 2
### Heading 3
#### Heading 4
##### Heading 5
###### Heading 6
```
## Text Formatting
Emphasize text with bold, italic, strikethrough, and inline code.
**Bold text**
_Italic text_
~~Strikethrough text~~
`Inline code`
```md
**Bold text**
*Italic text*
~~Strikethrough text~~
`Inline code`
```
## Lists
Create unordered lists with `-` and nest items by indenting them.
* Unordered list item
* Another item
* Nested item
* Another nested item
```md
- Unordered list item
- Another item
- Nested item
- Another nested item
```
Create ordered lists with numbers, nesting items the same way.
1. Ordered list item
2. Another item
1. Nested item
2. Another nested item
```md
1. Ordered list item
2. Another item
1. Nested item
2. Another nested item
```
## Links and Images
Link to absolute URLs, other Markdown files, and embed images.
[Absolute URLs](https://example.com)
[Relative link](/products/docs/components/tables)

```md
[Absolute URLs](https://example.com)
[Relative link](/products/docs/components/tables)

```
## Code Blocks
Wrap code in fenced blocks and add a language for syntax highlighting.
```javascript
function example() {
return "Hello, World!";
}
```
````md
```javascript
function example() {
return "Hello, World!";
}
```
````
## Blockquotes
Quote text with `>`, spanning multiple lines as needed.
> This is a blockquote
>
> It can span multiple lines
```md
> This is a blockquote
>
> It can span multiple lines
```
## Tables
We support standard GitHub-flavored Markdown tables.
| Header 1 | Header 2 | Header 3 |
| -------- | -------- | -------- |
| Cell 1 | Cell 2 | Cell 3 |
| Cell 4 | Cell 5 | Cell 6 |
```md
| Header 1 | Header 2 | Header 3 |
| -------- | -------- | -------- |
| Cell 1 | Cell 2 | Cell 3 |
| Cell 4 | Cell 5 | Cell 6 |
```
For alignment, escaping pipe characters, and best practices, see [Tables](/products/docs/components/tables).
## Task Lists
Track work with checkboxes using `- [ ]` for open items and `- [x]` for completed ones.
* [x] Completed task
* [ ] Pending task
* [ ] Another pending task
```md
- [x] Completed task
- [ ] Pending task
- [ ] Another pending task
```
## Hints
We support GitHub-style alerts for highlighting important information.
Useful information that users should know, even when skimming content.
Helpful advice for doing things better or more easily.
Key information users need to know to achieve their goal.
Urgent info that needs immediate user attention to avoid problems.
Advises about risks or negative outcomes of certain actions.
```md
> [!NOTE]
> Useful information that users should know, even when skimming content.
> [!TIP]
> Helpful advice for doing things better or more easily.
> [!IMPORTANT]
> Key information users need to know to achieve their goal.
> [!WARNING]
> Urgent info that needs immediate user attention to avoid problems.
> [!CAUTION]
> Advises about risks or negative outcomes of certain actions.
```
# Buttons
Buttons are interactive elements that link to external resources or other pages. Each button can include an icon and, by default, opens links in a new tab.
## Properties
| Prop | Type | Default | Description |
| --------- | ------------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `title` | `string` | _required_ | The label shown on the button. |
| `href` | `string` | _required_ | The URL the button links to. |
| `icon` | `string` | — | Icon shown before the label. Accepts a built-in [icon key](/products/docs/components/icons#built-in-icons) (Phosphor or Simple Icons) or a [custom URL](/products/docs/components/icons#custom-icons). |
| `variant` | `'primary'` `'secondary'` | `primary` | Visual style of the button. |
| `target` | `'_blank'` `'_self'` | `_blank` | Where the link opens. `_blank` adds `rel="noopener noreferrer"` automatically. |
## Examples
### Basic Button
[View Documentation](https://docs.scalar.com)
```md Markdown
```
```mdx MDX
```
### Button with Icon
[Download SDK](https://github.com/scalar/scalar)
```md Markdown
```
```mdx MDX
```
### Secondary Variant
[Learn More](https://scalar.com)
```md Markdown
```
```mdx MDX
```
# Callouts
Callouts are highlighted boxes that draw attention to important information. Each type has its own color and icon.
## Properties
| Prop | Type | Default | Description |
| ------ | ------------------------------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `type` | `'neutral'` `'success'` `'danger'` `'warning'` `'info'` | `neutral` | Visual style and default icon. Accepts the aliases `warn` and `information`. |
| `icon` | `string` | — | Overrides the default icon for the type. Accepts a built-in [icon key](/products/docs/components/icons#built-in-icons) (Phosphor or Simple Icons) or a [custom URL](/products/docs/components/icons#custom-icons). |
## Examples
### Basic Callout
This is an informational message.
```md Markdown
This is an informational message.
```
```mdx MDX
This is an informational message.
```
### All Types
Neutral message.
Informational message.
Success message.
Warning message.
Something went wrong.
```md Markdown
Neutral message.Informational message.Success message.Warning message.Something went wrong.
```
```mdx MDX
Neutral message.Informational message.Success message.Warning message.Something went wrong.
```
### Custom Icon
Operation completed successfully!
```md Markdown
Operation completed successfully!
```
```mdx MDX
Operation completed successfully!
```
## MDX Shortcuts
In MDX, the following named components are equivalent to `` with a preset `type`:
| Component | Equivalent |
| ----------- | ------------------------------------------- |
| `` | `` |
| `` | `` |
| `` | `` |
| `` | `` |
| `` | `` |
| `` | `` |
Useful information that's good to know.
Helpful advice for getting more out of a feature.
Something to be careful about.
Watch out — this can break things.
```mdx MDX
Useful information that's good to know.Helpful advice for getting more out of a feature.Something to be careful about.Watch out — this can break things.
```
# Math
Render mathematical equations using KaTeX and LaTeX syntax.
## Properties
| Prop | Type | Default | Description |
| ---------- | -------- | ------- | ------------------------------------------------------------- |
| `equation` | `string` | — | The LaTeX equation to render. May also be passed as children. |
| `caption` | `string` | — | Caption shown below the equation. |
The component accepts the equation either as the `equation` prop or as children. The `equation` prop takes precedence when both are provided.
## Examples
### Basic Equation
E=mc2
```md Markdown
```
```mdx MDX
```
### Equation as Children
∫0∞e−x2dx=2π
```md Markdown
\int_{0}^{\infty} e^{-x^2} dx = \frac{\sqrt{\pi}}{2}
```
```mdx MDX
```
### With a Caption
a2+b2=c2
Pythagorean theorem
```md Markdown
```
```mdx MDX
```
## MDX Shortcut
`` is an alias for `