Schema reference
Every field available in docs.json, with types, defaults, and constraints.
For an introduction to the file and how it fits into a deploy, see docs.json overview.
Full example
A docs.json with every field populated. Copy this and trim what you don't need.
{
"name": "Acme docs",
"description": "Documentation for Acme.",
"navigation": [
{
"tab": "Guide",
"groups": [
{
"group": "Get started",
"pages": ["quickstart", "introduction"]
},
{
"group": "Configuration",
"pages": ["configuration/docs-json", "configuration/theme"]
}
]
},
{
"group": "Reference",
"pages": ["reference/schema"]
},
{
"group": "API reference",
"openapi": "openapi.json"
}
],
"navbar": [
{ "name": "GitHub", "url": "https://github.com/acme/docs" },
{ "name": "Support", "url": "mailto:support@acme.com" }
],
"theme": {
"preset": "ocean",
"primaryOverride": "oklch(0.62 0.19 145)"
}
}Top-level fields
| Field | Type | Required | Default |
|---|---|---|---|
name | string | No | The subdomain |
description | string (≤ 160 chars) | No | None |
languages | array of language codes | No | Single language |
navigation | array of group or tab items | No | Empty sidebar |
navbar | array of { name, url } items | No | No links |
theme | { preset, primaryOverride? } | No | None |
All six fields are optional. A docs.json with {} is valid and renders the site with default name, no sidebar, no navbar links, and the unstyled fallback palette.
Bloques uses default as the fallback palette when
theme is unset, but you should set theme.preset explicitly so future
palette changes don't shift your site.
name
Site title. Used as the navbar brand text, the browser tab title, and the OpenGraph title for link previews.
| Property | Value |
|---|---|
| Type | string |
| Required | No |
| Default | The site's subdomain (for example, acme for acme.bloques.site) |
{ "name": "Acme docs" }description
One-sentence summary of the site. Used as the meta description and the OpenGraph description for link previews and search results.
| Property | Value |
|---|---|
| Type | string |
| Required | No |
| Max length | 160 characters |
| Default | None |
{ "description": "Documentation for Acme." }languages
Languages the site serves. Adding a second code turns on the language switcher and the per-language content folders. See Internationalization.
| Property | Value |
|---|---|
| Type | array of language codes |
| Required | No |
| Supported codes | en, es |
| Default | None — the site serves one language |
English (en) is always the default language. Other codes are served under a URL prefix (/es/...).
{ "languages": ["en", "es"] }navigation
Sidebar entries. An array of items, each either a group or a tab. The two shapes are mutually exclusive — a group has group and pages, a tab has tab and groups. See Navigation for ordering, labels, and hiding pages.
| Property | Value |
|---|---|
| Type | array of group or tab items (union) |
| Required | No |
| Default | Empty array (no sidebar entries) |
Group item
| Field | Type | Required | Notes |
|---|---|---|---|
group | string | Yes | Section label in the sidebar, rendered verbatim. |
pages | array<string | group> | No | Page paths repo-relative to the docs root, without .mdx. Entries can also be nested group items. Order is the render order. |
openapi | string | No | Path to an OpenAPI spec (JSON) in the docs directory, with extension. Generates one page per operation under the group. Works on a top-level group or a group directly inside a tab. |
Provide pages, openapi, or both. A group with openapi lists its operation pages after any pages you set. See API reference overview.
{
"group": "Get started",
"pages": ["quickstart", "introduction"]
}A group entry inside pages renders as a collapsible subsection. Pages in a nested group must share a folder prefix.
{
"group": "Editor",
"pages": [
"editor/overview",
{
"group": "Components",
"pages": ["editor/components/accordion", "editor/components/callout"]
},
"editor/images"
]
}Tab item
| Field | Type | Required | Notes |
|---|---|---|---|
tab | string | Yes | Tab label in the navbar, rendered verbatim. |
groups | array of group items | Yes | Groups shown when the tab is active. Same shape as a top-level group. |
{
"tab": "API reference",
"groups": [{ "group": "Endpoints", "pages": ["api/endpoints/create"] }]
}Groups and tabs can mix in the same navigation array. Groups can nest inside
other groups, but tabs don't nest inside other tabs.
navbar
External links shown in the top navigation bar. See Navbar.
| Property | Value |
|---|---|
| Type | array of { name, url } items |
| Required | No |
| Default | Empty array (no links) |
Navbar item
| Field | Type | Required | Notes |
|---|---|---|---|
name | string | Yes | Link label in the navbar. |
url | string | Yes | Any URL. URLs starting with http:// or https:// open in a new tab; others, the same tab. |
{
"navbar": [{ "name": "GitHub", "url": "https://github.com/acme/docs" }]
}theme
Color palette for the site. See Theme for previews and dark mode behavior.
| Property | Value |
|---|---|
| Type | { preset, primaryOverride? } |
| Required | No |
| Default | The default preset is applied |
Theme fields
| Field | Type | Required | Notes |
|---|---|---|---|
preset | "default" | "ocean" | "emerald" | "rose" | Yes | Built-in palette. Each preset includes a paired dark mode. |
primaryOverride | string | No | CSS color string replacing the preset's primary and focus ring. Accepts hex, rgb(), hsl(), oklch(), or a named color. |
{
"theme": {
"preset": "default",
"primaryOverride": "#10b981"
}
}primaryOverride is written verbatim into the site's CSS. Invalid color
strings render as no color, not as a validation error.
Validation
Bloques validates docs.json on every deploy. An invalid file fails the deploy and the site keeps serving the last good version. Common failures:
| Error | Cause |
|---|---|
description too long | Over 160 characters. |
theme.preset invalid | Value isn't one of the four preset IDs. |
Navigation item has neither group nor tab | Item is missing the discriminator field. |
Navigation item has both group and tab | Items are one or the other, not both. |
Group pages references a missing file | A path in pages doesn't resolve to an .mdx file in the repo. |
| Nested group has no pages | A nested group has an empty pages array. |
| Nested group pages don't share a folder | Pages inside a nested group resolve to no common folder prefix. |
| Sub-group escapes parent folder | A nested group's folder isn't a subfolder of its parent's folder. |
| Page escapes nested group folder | A page string in a nested group isn't inside the group's folder. |
A missing or invalid openapi spec doesn't fail the deploy. Bloques skips it and the rest of the site builds. See Set up an API reference for troubleshooting.