{"$schema":"http://json-schema.org/draft-07/schema#","$id":"https://app.octri.dev/schemas/octri.json","title":"octri.json","type":"object","properties":{"$schema":{"type":"string","description":"The JSON Schema this file follows. Editors use it for completions."},"appearance":{"type":"object","properties":{"colors":{"type":"object","properties":{"primary":{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$","description":"The brand colour: links, active rows, primary buttons. #rrggbb."}},"required":["primary"],"additionalProperties":false},"colorScheme":{"type":"string","enum":["system","light","dark"],"description":"The scheme a reader starts in. \"system\" follows their operating system."},"themeToggle":{"type":"boolean","description":"Show the light and dark switch in the top bar."},"layout":{"type":"string","enum":["full","contained","framed","floating"],"description":"How the page is framed. \"full\": sidebar and rail at the screen edges. \"contained\": one centred block. \"framed\": content on a raised panel. \"floating\": the sidebar as a card held off the edges."},"contentWidth":{"type":"string","enum":["narrow","default","wide"],"description":"Width of the reading column."},"corners":{"type":"string","enum":["sharp","default","rounded"],"description":"Corner rounding across the site. \"rounded\" also turns buttons and badges into pills."},"logo":{"type":"object","properties":{"light":{"type":"string","maxLength":500,"description":"Logo image URL for the light scheme, and for both when `dark` is empty."},"dark":{"type":"string","maxLength":500,"description":"Logo image URL for the dark scheme. Empty uses the light logo."},"link":{"type":"string","maxLength":500,"description":"Where clicking the logo goes: a path or a full URL. Empty means the docs home."},"show":{"type":"boolean","description":"false draws the project name instead of the logo, keeping the URLs above."}},"additionalProperties":false},"favicon":{"type":"string","maxLength":500,"description":"Favicon image URL."},"fonts":{"type":"object","properties":{"body":{"type":"string","enum":["manrope","inter","plus-jakarta-sans","dm-sans","system","google"],"description":"Body text face. \"google\" uses the family named in `google.body`."},"heading":{"type":"string","enum":["body","manrope","inter","plus-jakarta-sans","dm-sans","google"],"description":"Heading face. \"body\" matches the body text."},"code":{"type":"string","enum":["jetbrains-mono","fira-code","ibm-plex-mono","system","google"],"description":"Face for code panels and inline code."},"google":{"type":"object","properties":{"body":{"type":"string","maxLength":80,"description":"Google Fonts family for body text, e.g. \"Roboto\"."},"heading":{"type":"string","maxLength":80,"description":"Google Fonts family for headings."},"code":{"type":"string","maxLength":80,"description":"Google Fonts family for code."}},"additionalProperties":false,"description":"Google Fonts family names, read by any slot set to \"google\"."}},"additionalProperties":false},"textSize":{"type":"object","properties":{"sidebar":{"type":"string","enum":["smaller","large","larger"],"description":"Sidebar text size."},"content":{"type":"string","enum":["smaller","large","larger"],"description":"Main panel text size."},"code":{"type":"string","enum":["smaller","large","larger"],"description":"Code example text size, set apart from the page."}},"additionalProperties":false},"sidebar":{"type":"object","properties":{"style":{"type":"string","enum":["default","bordered","minimal"],"description":"How sidebar rows are drawn."},"width":{"type":"string","enum":["compact","default","wide"],"description":"Starting sidebar width."},"resizable":{"type":"boolean","description":"Let readers drag the sidebar wider or narrower."},"lines":{"type":"boolean","description":"Draw a line down each folder's children."},"icons":{"type":"boolean","description":"Show folder, page and link icons."}},"additionalProperties":false},"navbar":{"type":"object","properties":{"layout":{"type":"string","enum":["default","stacked","centered"],"description":"\"default\": one row. \"stacked\": tabs on a second row. \"centered\": tabs in the middle."},"search":{"type":"string","enum":["sidebar","centered","button"],"description":"Where search sits: top of the \"sidebar\", \"centered\" in the top bar, or a \"button\"."},"surface":{"type":"string","enum":["solid","frosted","transparent","colored"],"description":"What the top bar is made of. \"colored\" fills it with `color`."},"color":{"type":"object","properties":{"light":{"type":"string","pattern":"^(#[0-9A-Fa-f]{6})?$","description":"Top bar fill in the light scheme. Empty uses the primary colour."},"dark":{"type":"string","pattern":"^(#[0-9A-Fa-f]{6})?$","description":"Top bar fill in the dark scheme. Empty uses the primary colour."}},"additionalProperties":false,"description":"Read only while `surface` is \"colored\"."}},"additionalProperties":false},"codeTheme":{"type":"object","properties":{"light":{"type":"string","enum":["octri","github","monokai","nord","dracula"],"description":"Code highlighting in the light scheme."},"dark":{"type":"string","enum":["octri","github","monokai","nord","dracula"],"description":"Code highlighting in the dark scheme."}},"additionalProperties":false},"tableOfContents":{"type":"object","properties":{"endpoints":{"type":"boolean","description":"The \"On this page\" rail on endpoint pages."},"pages":{"type":"boolean","description":"The \"On this page\" rail on written pages."}},"additionalProperties":false},"repository":{"type":"object","properties":{"url":{"type":"string","maxLength":300,"description":"Source repository linked from the top bar. Empty for none."},"stars":{"type":"boolean","description":"Show the repository's star count beside the link."}},"additionalProperties":false}},"additionalProperties":false,"description":"How the docs site looks. Saving applies these straight away, like the Appearance panel."},"navigation":{"type":"object","properties":{"tabs":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string","maxLength":200,"description":"The tab's name in the top bar."},"type":{"type":"string","enum":["reference","content","link","changelog"],"description":"\"reference\": every endpoint, kept current for you. \"content\": a sidebar you build from `items`. \"link\": a top bar link to `url`. \"changelog\": the project's release feed."},"path":{"type":"string","maxLength":60,"pattern":"^([a-z0-9]+(-[a-z0-9]+)*)?$","description":"The tab's first URL segment, e.g. \"guides\". Leave it out to follow the label."},"url":{"type":"string","maxLength":2000,"description":"Where a \"link\" tab goes."},"icon":{"type":"string","maxLength":64,"pattern":"^[a-z0-9-]*$","description":"An icon from the docs icon set, e.g. \"rocket\". \"none\" draws no icon. Leave it out for the default mark."},"hidden":{"type":"boolean","description":"true keeps the tab out of the published top bar."},"items":{"type":"array","items":{"$ref":"#/definitions/row"},"maxItems":500,"description":"The tab's sidebar, top to bottom. On a \"reference\" tab these are the folders you arranged; every other endpoint is listed for you."},"hide":{"type":"array","items":{"type":"string","minLength":1,"maxLength":400},"maxItems":2000,"description":"Pages and endpoints this tab would list on its own but readers should not see, e.g. \"GET /internal/health\". On a \"reference\" tab, this is how an endpoint is kept out of the sidebar."}},"required":["label","type"],"additionalProperties":false},"maxItems":50,"description":"The top bar's tabs, left to right. Saved as a draft: Publish to apply."},"buttons":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":40,"description":"The button's text."},"url":{"type":"string","maxLength":2000,"description":"Where it goes: an http(s) URL, a mailto: address or a path starting with /."},"style":{"type":"string","enum":["plain","outline","primary"],"description":"\"plain\" text, \"outline\" or a filled \"primary\" button."}},"required":["label","url"],"additionalProperties":false},"maxItems":3,"description":"Call-to-action buttons at the right of the top bar, at most 3. Applied on save."},"home":{"anyOf":[{"type":"object","properties":{"page":{"type":"string","minLength":1,"maxLength":400,"description":"The page served at the docs root, /."},"hideSidebar":{"type":"boolean","description":"Draw the home page without the sidebar and the \"On this page\" rail."}},"required":["page"],"additionalProperties":false},{"type":"null"}],"description":"The docs home page, or null for none. Saved as a draft: Publish to apply."},"redirects":{"type":"array","items":{"type":"object","properties":{"from":{"type":"string","maxLength":301,"description":"The old path on your docs site, starting with /. End it in /* to match everything under it."},"to":{"type":"string","maxLength":301,"description":"Where readers go instead: a path on the same site. End it in /* to carry the rest of the path across."},"force":{"type":"boolean","description":"true for a page that redirects: `from` and `to` are page addresses like /guides/old-page, and readers of the page go to `to` even though it is still published. Set from the page's own dialog."}},"required":["from","to"],"additionalProperties":false},"maxItems":500,"description":"Old paths and where readers go instead, checked in order. A page at the old path always wins. Saved as a draft: Publish to apply."}},"required":["tabs"],"additionalProperties":false},"socials":{"type":"object","properties":{"github":{"type":"string","maxLength":500,"description":"Your github URL. Leave it out for no icon."},"gitlab":{"type":"string","maxLength":500,"description":"Your gitlab URL. Leave it out for no icon."},"x":{"type":"string","maxLength":500,"description":"Your x URL. Leave it out for no icon."},"linkedin":{"type":"string","maxLength":500,"description":"Your linkedin URL. Leave it out for no icon."},"youtube":{"type":"string","maxLength":500,"description":"Your youtube URL. Leave it out for no icon."},"instagram":{"type":"string","maxLength":500,"description":"Your instagram URL. Leave it out for no icon."},"facebook":{"type":"string","maxLength":500,"description":"Your facebook URL. Leave it out for no icon."},"tiktok":{"type":"string","maxLength":500,"description":"Your tiktok URL. Leave it out for no icon."},"reddit":{"type":"string","maxLength":500,"description":"Your reddit URL. Leave it out for no icon."},"discord":{"type":"string","maxLength":500,"description":"Your discord URL. Leave it out for no icon."},"slack":{"type":"string","maxLength":500,"description":"Your slack URL. Leave it out for no icon."},"telegram":{"type":"string","maxLength":500,"description":"Your telegram URL. Leave it out for no icon."},"whatsapp":{"type":"string","maxLength":500,"description":"Your whatsapp URL. Leave it out for no icon."},"twitch":{"type":"string","maxLength":500,"description":"Your twitch URL. Leave it out for no icon."},"mastodon":{"type":"string","maxLength":500,"description":"Your mastodon URL. Leave it out for no icon."},"medium":{"type":"string","maxLength":500,"description":"Your medium URL. Leave it out for no icon."},"devto":{"type":"string","maxLength":500,"description":"Your devto URL. Leave it out for no icon."},"stackoverflow":{"type":"string","maxLength":500,"description":"Your stackoverflow URL. Leave it out for no icon."},"npm":{"type":"string","maxLength":500,"description":"Your npm URL. Leave it out for no icon."},"producthunt":{"type":"string","maxLength":500,"description":"Your producthunt URL. Leave it out for no icon."},"website":{"type":"string","maxLength":500,"description":"Your website URL. Leave it out for no icon."},"custom":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string","minLength":1,"maxLength":40,"description":"The link's name."},"url":{"type":"string","maxLength":500,"minLength":1,"description":"Where it goes."},"icon":{"type":"string","maxLength":64,"pattern":"^[a-z0-9-]*$","description":"An icon from the docs set, or \"\" to draw the label as a button."}},"required":["label","url"],"additionalProperties":false},"maxItems":5,"description":"Links of your own, in order, at most 5."}},"additionalProperties":false,"description":"Social links under each page. Applied on save."},"seo":{"type":"object","properties":{"enabled":{"type":"boolean","description":"false turns off all search and social metadata: no link previews, no canonical links, no sitemap, no llms.txt, and every page asks not to be indexed."},"titleMode":{"type":"string","enum":["dynamic","static"],"description":"\"dynamic\": each page's own title, written through `titleTemplate`. \"static\": `title` on every page."},"title":{"type":"string","maxLength":120,"description":"The site's title. Empty uses the project name."},"titleTemplate":{"type":"string","maxLength":120,"description":"How a page title is written while `titleMode` is \"dynamic\"; %s is the page's title. Empty means \"%s | <title>\"."},"description":{"type":"string","maxLength":300,"description":"What search results and link previews show for the home page, and for any page without a description of its own."},"ogImage":{"type":"string","maxLength":500,"description":"Image URL for link previews on social sites and chat apps."},"keywords":{"type":"string","maxLength":300,"description":"Keywords, separated by commas."},"indexable":{"type":"boolean","description":"false asks search engines not to index or crawl the docs. Link previews keep working."},"twitter":{"type":"string","maxLength":40,"description":"Your X (Twitter) handle for link previews, without the @."}},"additionalProperties":false,"description":"How the docs appear in search results and link previews. Applied on save."},"feedback":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Ask \"Was this helpful?\" at the bottom of every page. Votes are anonymous and show in Analytics."}},"additionalProperties":false,"description":"Page feedback from readers. Applied on save."},"playground":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Show the \"Try it\" playground on endpoint pages."},"baseUrl":{"type":"string","maxLength":2048,"description":"Where try-it requests go. Empty follows the project's API server, as the SDKs do."},"auth":{"type":"object","properties":{"type":{"type":"string","enum":["inherit","none","apiKey","basic","bearer","oauth2"],"description":"The credential a reader fills in. \"inherit\" follows the project's API server setting."},"headerName":{"type":"string","minLength":1,"maxLength":120,"description":"The header the credential is sent in, e.g. \"Authorization\" or \"X-API-Key\"."}},"additionalProperties":false},"allowedOrigins":{"type":"array","items":{"type":"string","maxLength":255},"maxItems":20,"description":"Sites besides your docs that may send requests through the playground, e.g. \"https://example.com\"."},"timeoutMs":{"type":"integer","minimum":1000,"maximum":60000,"description":"How long a try-it request may run before it is abandoned, in milliseconds."}},"additionalProperties":false,"description":"The \"Try it\" playground on endpoint pages. Applied on save."},"customCode":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Load the files in custom-code/ on every docs page. false keeps them saved but unused."}},"additionalProperties":false,"description":"Your own CSS and HTML on every page, on the Growth plan and above. The code itself is in custom-code/. Applied on save."},"components":{"type":"object","propertyNames":{"type":"string","pattern":"^[A-Z][A-Za-z0-9]*$","description":"A custom component's tag."},"additionalProperties":{"type":"object","properties":{"description":{"type":"string","maxLength":500,"description":"What the component is for, shown in the editor's component menu."},"props":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":60,"pattern":"^[A-Za-z_][A-Za-z0-9_]*$","description":"What an author writes in the tag: `title` in <Hero title=\"Welcome\">."},"type":{"type":"string","enum":["string","number","boolean","color","node","select"],"description":"\"node\" takes markup. \"select\" takes one of `options`. The others take what they say."},"default":{"type":"string","maxLength":500,"description":"The value used when an author leaves the prop out."},"description":{"type":"string","maxLength":500,"description":"Help text the editor shows beside the prop."},"options":{"type":"array","items":{"type":"string","minLength":1,"maxLength":60},"maxItems":20,"description":"The choices a \"select\" prop offers, in order."}},"required":["name","type"],"additionalProperties":false},"maxItems":40,"description":"The props an author can set, in the order the editor lists them."}},"additionalProperties":false},"description":"Your custom components by tag, on the Growth plan and above. Each one's template and CSS are files in components/. Components are created and deleted in Docs settings; one left out of this list is left as it is. Applied on save."}},"additionalProperties":false,"definitions":{"row":{"anyOf":[{"type":"string","minLength":1,"maxLength":400,"description":"A page (\"quickstart\") or an endpoint (\"GET /users\"), with no other settings."},{"type":"object","properties":{"page":{"type":"string","minLength":1,"maxLength":400,"description":"A page by where it sits: its tab, its folders, then its name, as in its docs URL, e.g. \"guides/getting-started/quickstart\". The same path as its file under pages/. A name no page has makes a new page."},"label":{"type":"string","maxLength":200,"description":"Sidebar text. Leave it out to use the page's title."},"icon":{"type":"string","maxLength":64,"pattern":"^[a-z0-9-]*$","description":"An icon from the docs icon set, e.g. \"rocket\". \"none\" draws no icon. Leave it out for the default mark."},"hidden":{"type":"boolean","description":"true keeps the entry out of the published sidebar. The page itself still exists."},"path":{"type":"string","maxLength":200,"pattern":"^([a-z0-9]+(-[a-z0-9]+)*)?$","description":"This entry's own segment in the URL. Leave it out to follow the name."}},"required":["page"],"additionalProperties":false},{"type":"object","properties":{"endpoint":{"type":"string","minLength":1,"maxLength":400,"description":"An endpoint as \"METHOD /path\", e.g. \"GET /users/{id}\"."},"label":{"type":"string","maxLength":200,"description":"Sidebar text. Leave it out to use the endpoint's title."},"icon":{"type":"string","maxLength":64,"pattern":"^[a-z0-9-]*$","description":"An icon from the docs icon set, e.g. \"rocket\". \"none\" draws no icon. Leave it out for the default mark."},"hidden":{"type":"boolean","description":"true keeps the entry out of the published sidebar. The page itself still exists."},"path":{"type":"string","maxLength":200,"pattern":"^([a-z0-9]+(-[a-z0-9]+)*)?$","description":"This entry's own segment in the URL. Leave it out to follow the name."}},"required":["endpoint"],"additionalProperties":false},{"type":"object","properties":{"link":{"type":"string","minLength":1,"maxLength":400,"description":"Where the row goes: a full URL or a path on this site."},"label":{"type":"string","maxLength":200,"description":"The row's text."},"icon":{"type":"string","maxLength":64,"pattern":"^[a-z0-9-]*$","description":"An icon from the docs icon set, e.g. \"rocket\". \"none\" draws no icon. Leave it out for the default mark."},"hidden":{"type":"boolean","description":"true keeps the entry out of the published sidebar. The page itself still exists."}},"required":["link","label"],"additionalProperties":false},{"type":"object","properties":{"folder":{"type":"string","maxLength":200,"description":"The folder's name. \"\" groups its rows under no heading."},"items":{"type":"array","items":{"$ref":"#/definitions/row"},"maxItems":500,"description":"Rows and folders inside, in order."},"icon":{"type":"string","maxLength":64,"pattern":"^[a-z0-9-]*$","description":"An icon from the docs icon set, e.g. \"rocket\". \"none\" draws no icon. Leave it out for the default mark."},"badge":{"type":"string","maxLength":24,"description":"A short word after the name, e.g. \"New\"."},"badgeColor":{"type":"string","enum":["accent","gray","green","blue","amber","red","purple"],"description":"The badge's colour. \"accent\" is the primary colour."},"page":{"type":"string","minLength":1,"maxLength":400,"description":"A page the folder's name opens."},"collapsible":{"type":"boolean","description":"false keeps the folder always open, with no chevron."},"hidden":{"type":"boolean","description":"true keeps the entry out of the published sidebar. The page itself still exists."},"path":{"type":"string","maxLength":200,"pattern":"^([a-z0-9]+(-[a-z0-9]+)*)?$","description":"This entry's own segment in the URL. Leave it out to follow the name."}},"required":["folder","items"],"additionalProperties":false}]}}}