docs.json reference

Every configuration field, with a working example for each.

docs.json reference

docs.json at your project root is the single source of configuration. Add "$schema": "./docs.config.schema.json" (run fiskil schema to generate the file) and your editor autocompletes everything below; fiskil validate is the authority, and it runs automatically before dev, build, and publish.

At a glance

KeyTypeRequiredPurpose
namestringSite name: page titles, search, social cards
descriptionstringSite-wide meta description
siteUrlURLCanonical origin; enables the sitemap
ogImagepathSite-wide social share image
themeobjectYesColors — the only required key
logoobjectHeader wordmark, light/dark
productsarrayTop-level product switcher
i18nobjectLocales and translation behavior
openapiobjectAPI references from OpenAPI specs
fontsobjectCustom typography (Fonts)
seoobjectDe-indexing, structured data, meta tags (SEO)
redirectsarrayURL redirects (Redirects)
errorsobjectCustom 404 page (Custom 404)
integrationsobjectAnalytics (PostHog)

Unknown top-level keys are ignored rather than rejected — adding new sections in future versions is never a breaking change for your file.

name, description, siteUrl, ogImage

{
  "name": "Acme",
  "description": "Developer documentation for the Acme platform.",
  "siteUrl": "https://docs.acme.com",
  "ogImage": "/og.png"
}
  • name feeds the title template (Page title | Acme Docs), the generated home, and llms.txt. Defaults to "Docs".
  • siteUrl is what makes the sitemap non-empty and absolute URLs resolvable — set it as soon as you know your domain.
  • ogImage must be an absolute path under public/.

theme

The one required key. A single color rebrands the whole site; the rest is optional refinement.

{
  "theme": {
    "colors": {
      "primary": "#0033A9",
      "light": "#4D79FF",
      "dark": "#00227A",
      "status": { "warning": "#B45309" },
      "accents": ["#00AFCC", "#E4E729"]
    }
  }
}
FieldRequiredWhat it drives
colors.primaryYesLinks, active states, brand moments
colors.lightDark-mode emphasis; falls back to primary
colors.darkButtons and hover; falls back to primary
colors.statusCallout palette: info, warning, error, success, idea
colors.accentsUp to 4 section-accent colors, exposed to your pages as --color-accent-1..4 (plus generated soft/gradient tints)

Colors are 3- or 6-digit hex. See Branding for how these flow into components.

{
  "logo": {
    "light": "/logo/wordmark.svg",
    "dark": "/logo/wordmark-dark.svg"
  }
}

Replaces the text site name in the header. Paths are under public/; dark is optional and falls back to light. Favicons are convention, not config — drop favicon.svg, favicon.ico, icon.png, or apple-touch-icon.png into public/ and the tags are emitted automatically.

products

{
  "products": [
    { "id": "payments", "label": "Payments API" },
    { "id": "terminals", "label": "Terminals" }
  ]
}

Each product is a top-level content area at /{id}/... with its own section tabs and sidebar. id is lowercase letters, digits, and hyphens; it's also the folder name under content/docs/. A product id may not collide with a locale code.

i18n

{
  "i18n": {
    "locales": ["en", "es", "pt-BR"],
    "default": "en",
    "fallback": "show-default-with-banner",
    "localeLabels": { "pt-BR": "Português" },
    "translations": { "es": { "search.placeholder": "Buscar..." } },
    "searchLanguages": { "pt-BR": "portuguese" }
  }
}
FieldRequiredNotes
localesYes (within i18n)Locale codes like en or pt-BR
defaultYes (within i18n)Served unprefixed; must be in locales
fallbackUntranslated pages show the default-locale content with a language banner (show-default-with-banner, the default and currently the only implemented behavior)
localeLabelsLanguage-switcher names; unlisted locales show the uppercased code
translationsOverride any built-in UI string per locale
searchLanguagesSearch stemmer per locale, only when the ISO code isn't auto-mapped

Content layout and workflow live in Locales.

openapi

{
  "openapi": {
    "apis": [
      {
        "product": "payments",
        "label": "Payments API",
        "specs": [{ "spec": "payments.json", "useFirstTagOnly": true }]
      }
    ]
  }
}

Each entry in apis mounts a generated API reference at /{product}/{section} (section defaults to api-reference). A reference is exactly one of: flat specs, versioned versions, or grouped groups. The full model — per-spec options, versioning, groups, sidebar sections — has its own chapter: API docs.

seo

{
  "seo": { "noindex": ["/internal", "/es"] }
}

Path prefixes listed in noindex are excluded from the sitemap, disallowed in robots.txt, and marked noindex in page metadata — one setting, all three surfaces. Matching respects path boundaries (/es never matches /essentials). Per-page control exists too: noindex: true in frontmatter. More in SEO.

integrations

{
  "integrations": {
    "posthog": {
      "apiKey": "phc_your_publishable_key",
      "apiHost": "https://eu.i.posthog.com"
    }
  }
}

Keys here are publishable client tokens — safe to commit. apiHost is optional (defaults to PostHog US cloud). Pageviews, including client-side navigations, are tracked automatically. Details in Analytics.

Validation

Two layers keep the file honest:

  • Editor: fiskil schema writes docs.config.schema.json for IntelliSense (--check verifies it's current in CI).
  • Authoritative: fiskil validate enforces everything the JSON Schema can't express — cross-references like every openapi.apis[].product matching a declared product, unique version ids, one default version, and mutual exclusivity of specs/versions/groups.