Scalar Docs Configuration Skill — scalar.config.json
Reference for writing and updating scalar.config.json, the central configuration file for Scalar Docs. Use this when creating, editing, or validating Docs configuration for any project.
Overview
- File:
scalar.config.json(orscalar.config.json5) - Location: Repository root by default; path can be overridden in Scalar Dashboard
- Schema:
https://registry.scalar.com/@scalar/schemas/config— enables autocomplete in VS Code/Cursor whenjson.schemaDownload.enableis true - Version: Use
"scalar": "2.0.0"for the latest format
Quick Start
Create a minimal config:
npx @scalar/cli project init
Minimal structure:
{
"$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"
}
}
}
}
Validate config: npx @scalar/cli project check-config
Root Properties
| Property | Type | Description |
|---|---|---|
$schema |
string |
JSON Schema URL for editor autocomplete and validation |
scalar |
string |
Configuration version. Use "2.0.0" |
info |
object |
Project metadata (title, description) |
navigation |
object |
Navigation structure (header, routes, sidebar, tabs) |
versions |
object |
Multi-version navigation. Use instead of navigation for versioned docs |
siteConfig |
object |
Site-level settings (domain, theme, head, logo, routing) |
assetsDir |
string |
Relative path to assets folder from config root |
info
Project metadata displayed across the site:
{
"info": {
"title": "My Documentation",
"description": "Comprehensive guides for our API"
}
}
navigation
All navigation is in navigation.routes. Each route key is the URL path; the value is a config object.
navigation.header
Links in the top bar. Use type: "spacer" to push items before it left and after it right.
"header": [
{ "type": "link", "title": "Home", "to": "/" },
{ "type": "spacer" },
{ "type": "link", "title": "Log in", "to": "https://dashboard.example.com/login", "newTab": true },
{ "type": "link", "title": "Register", "style": "button", "icon": "phosphor/regular/user-plus", "to": "https://...", "newTab": true }
]
Properties: title, type ("link" | "spacer"), to, style ("button" | "link"), icon, newTab
The header only renders when this array has at least one item, and it is where the logo goes. A lone { "type": "spacer" } is enough to get a header with just the logo.
navigation.sidebar
Links at the bottom of the sidebar:
"sidebar": [
{ "title": "Log in", "to": "https://...", "newTab": true }
]
navigation.tabs
Tabs for quick access to sections:
"tabs": [
{ "title": "API", "to": "/api", "icon": "phosphor/regular/plug" }
]
Tabs and a header work together, and neither requires the other. With tabs but no header, the logo renders in the tab bar.
Route Types
Page (type: "page")
Markdown/MDX content from a file:
"/getting-started": {
"type": "page",
"title": "Getting Started",
"filepath": "docs/getting-started.md",
"description": "Optional SEO description",
"icon": "phosphor/regular/rocket",
"showInSidebar": true,
"layout": { "toc": true, "sidebar": true }
}
Layout: toc (default true), sidebar (default true).
Hidden pages: Set showInSidebar: false to hide a page from the sidebar while keeping it accessible via its direct URL.
OpenAPI (type: "openapi")
API reference from file, Registry, or URL:
File:
"/api": {
"type": "openapi",
"title": "My API",
"filepath": "docs/api-reference/openapi.yaml",
"icon": "phosphor/regular/plug"
}
Registry:
"/api": {
"type": "openapi",
"title": "My API",
"namespace": "my-organization",
"slug": "your-api"
}
URL:
"/api": {
"type": "openapi",
"title": "My API",
"url": "https://example.com/openapi.json"
}
Display modes: folder (default), flat, nested.
Single page mode: Set singlePage: true to render all operations on a single page instead of creating separate pages for each operation:
"/api": {
"type": "openapi",
"title": "My API",
"filepath": "docs/api-reference/openapi.yaml",
"singlePage": true
}
API Reference options (authentication, theme, etc.) go in a config object — same options as the API Reference configuration.
Group (type: "group")
Collapsible section with children:
"/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" }
}
}
Modes: flat, nested, folder (default).
Folder landing pages: Add a page property to make clicking the folder navigate to a page:
"/company": {
"type": "group",
"title": "Company",
"mode": "folder",
"page": { "type": "page", "title": "About Us", "filepath": "docs/company/index.md" },
"children": {
"/team": { "type": "page", "title": "Our Team", "filepath": "docs/company/team.md" }
}
}
Default open state: Use open: true to expand a folder by default.
Link (type: "link")
External URL:
"/github": {
"type": "link",
"title": "GitHub",
"url": "https://github.com/org/repo",
"icon": "phosphor/regular/github-logo"
}
siteConfig
branding
Logo — single URL or per mode:
"logo": "https://example.com/logo.svg"
// or
"logo": {
"darkMode": "https://example.com/logo-dark.svg",
"lightMode": "https://example.com/logo-light.svg"
}
The logo renders on the first surface the site has: header (if navigation.header has items) → tabs (if navigation.tabs but no header) → sidebar (if neither). A page that hides all three via layout does not render it at all. With no logo set, info.title renders in the same place.
Theme — one of: default, alternate, moon, purple, solarized, bluePlanet, deepSpace, saturn, kepler, mars, laserwave, none
"theme": "purple"
domain
Subdomain (free): https://<subdomain>.apidocumentation.com
"subdomain": "your-docs"
Custom domain (Pro): https://docs.example.com
"customDomain": "docs.example.com"
Subpath — for multiple projects on same domain:
"subpath": "/guides"
layout
"layout": {
"toc": true,
"header": true
}
head
Inject scripts, styles, meta tags, and links:
"head": {
"title": "My Documentation",
"meta": [
{ "name": "description", "content": "API documentation" },
{ "property": "og:image", "content": "https://example.com/og.png" }
],
"styles": [{ "path": "docs/assets/custom.css", "tagPosition": "head" }],
"scripts": [{ "path": "docs/assets/analytics.js", "tagPosition": "bodyClose" }],
"links": [{ "rel": "icon", "href": "/favicon.png" }]
}
For scripts and styles: path relative to config root. For links (favicon): root-relative (/favicon.png).
tagPosition: "head" | "bodyOpen" | "bodyClose".
footer
"footer": {
"filepath": "docs/footer.html"
}
rss
Publishes an RSS feed for your changelog or blog so readers can subscribe. Written to <path>/rss.xml — a changelog at /changelog publishes its feed at /changelog/rss.xml.
"rss": {
"path": "/changelog",
"title": "Scalar Changelog",
"description": "Every Scalar release, as a feed"
}
| Property | Type | Required | Description |
|---|---|---|---|
path |
string |
Yes | Changelog route, e.g. /changelog. No .. segments |
title |
string |
No | Feed title. Defaults to your site title plus Changelog |
description |
string |
No | Feed description |
entries |
string |
No | headings (default) or pages — see below |
To publish several feeds, set rss to a list of these objects. Each needs its own unique path and is written to <path>/rss.xml:
"rss": [
{ "path": "/changelog", "title": "Scalar Changelog" },
{ "path": "/blog", "title": "Scalar Blog" }
]
Entries come from dated headings (## 1.2.0 (2026-07-24)) on the page at path or any page beneath it, merged newest-first. Only the top-most dated heading level starts entries; deeper headings (dated or not) fold into the release above them. Hidden pages are skipped. Every page advertises the feed with a <link rel="alternate" type="application/rss+xml"> tag, and pages under path show a subscribe button in the page header.
Set entries to pages for a blog instead: every page under path with a date in its frontmatter (date: 2026-07-24) becomes one item, titled by the page. Pages without a date (an index, a draft) are skipped. Use the default headings for a changelog.
routing
Redirects:
"routing": {
"redirects": [
{ "from": "/old-path", "to": "/new-path" },
{ "from": "/old-path/:wildcard", "to": "/new-path" },
{ "from": "/old-path/:pathMatch(.*)*", "to": "/new-path" }
]
}
Path patterns:
"routing": {
"guidePathPattern": "/docs/:slug",
"referencePathPattern": "/api/:slug"
}
assetsDir
Relative path to assets folder. Assets are served from site root.
"assetsDir": "docs/assets"
In Markdown:  or .
In siteConfig.head: use full path relative to config root for scripts/styles; root-relative for links.
Migration from Docs 1.0
Docs 1.0 used guides and references arrays. Docs 2.0 uses navigation.routes.
Upgrade:
npx @scalar/cli project upgrade
Check result:
npx @scalar/cli project preview
CLI Commands
| Command | Description |
|---|---|
npx @scalar/cli project init |
Create scalar.config.json |
npx @scalar/cli project check-config |
Validate config |
npx @scalar/cli project preview |
Local preview (port 7970) |
npx @scalar/cli project publish |
Publish from local files |
npx @scalar/cli project publish --github |
Publish from linked GitHub repo |
npx @scalar/cli project upgrade |
Migrate from Docs 1.0 |
Versions
Use versions instead of navigation to create multi-version documentation.
A version with the key default is required — it is the version shown by default. Additional versions (for example v1) can use any identifier and appear in the version selector. Inside each version's routes, wrap pages in a top-level group so they render correctly in the sidebar.
{
"scalar": "2.0.0",
"versions": {
"default": {
"title": "Version 2.0",
"routes": {
"/": {
"type": "group",
"title": "Documentation",
"children": {
"/": { "type": "page", "title": "Intro", "filepath": "docs/v2/intro.md" },
"/api": { "type": "openapi", "title": "API", "filepath": "docs/v2/openapi.yaml" }
}
}
}
},
"v1": {
"title": "Version 1.0",
"routes": {
"/": {
"type": "group",
"title": "Documentation",
"children": {
"/": { "type": "page", "title": "Intro", "filepath": "docs/v1/intro.md" },
"/api": { "type": "openapi", "title": "API", "filepath": "docs/v1/openapi.yaml" }
}
}
}
}
}
}
Each version entry supports: title, routes (required), header, sidebar, tabs.
Common Patterns
Multi-project on same domain: Same customDomain or subdomain, different subpath per repo.
MDX: Use .mdx extension in filepath; same structure as Markdown pages.
Hide TOC on a page: "layout": { "toc": false } on that route.
API Reference auth: Add config under the openapi route with authentication (same options as API Reference config).
Custom domain DNS: CNAME host docs → dns.scalar.com (DNS-only, no proxy).