Site settings

Reading time 8 min

Reader configuration has two layers: the installation’s siteconfig.json, and a selected private site-settings.json containing safe runtime overrides. A browser theme preference is a different layer and does not change either file. Settings affect the next build; they do not rewrite an already deployed reader.

This page uses Field Guide at an illustrative domain. Choose the intended root or subpath before writing links and deploying. JSON examples are configuration files, not shell commands. Keep a recoverable copy of current settings before changing them.

Where settings come from

Layer Purpose and precedence
Built-in defaults Safe branding fallback when a field is absent or its base value fails validation
File configuration Installation siteconfig.json; provides branding and file-only policy
Runtime overrides Selected data directory’s site-settings.json; valid safe keys override effective branding
Browser preference Theme/local reading state; does not configure the build

The builder reads siteconfig.json beside build.js, not beside a custom --content directory. It captures the raw-HTML flag from that file before applying runtime overrides. A custom content tree does not bring its own static assets, templates or site configuration automatically.

For build runtime data, selection is --data first, then MARKSTACK_DATA_DIR, then the parent directory of MARKSTACK_USERS_FILE, then the project’s .markstack. Relative selectors resolve against the process working directory. The editor instead keeps runtime data beside its selected users file. Align those choices deliberately; a build-only variable does not relocate editor accounts.

Complete domain-root example

Save valid JSON in the installation’s siteconfig.json:

{
  "siteTitle": "Field Guide",
  "headerTitle": "Field Guide",
  "siteSubtitle": "Practical guides for the team.",
  "siteUrl": "https://docs.example.com",
  "baseUrl": "",
  "defaultDescription": "Field Guide documentation and reference.",
  "showHero": false,
  "allowRawHtml": false,
  "copyrightText": "Copyright 2026 Field Guide contributors"
}

docs.example.com is an example address, not a deployed service. Review the actual site address before a real build. This example disables the home hero because content/_index.md already introduces the site. It does not disable home content or navigation.

Run npm run build, then npm run serve from that checkout. Inspect home, a deep page, header label, browser title, description metadata, search, assets and page URLs. npm run serve previews default dist/; it does not follow a previous custom output flag. A normal build clears selected output after URL preflight, so never use source/private storage as output.

Safe branding fields

These fields may come from file configuration or Admin runtime settings. Limits apply to the string before trimming and use JavaScript string length, not an encoded byte count or a count of visible graphemes.

Display field Key and effect
Site title siteTitle: optional home hero heading
Header title headerTitle: header label and browser-title suffix
Subtitle siteSubtitle: optional home hero subtitle
Description defaultDescription: fallback generated page-description metadata
Public address siteUrl: prefix used for generated page metadata URLs
Home hero showHero: show/hide title/subtitle block above home Markdown
Field Default and validation
Site title Knowledge Base; nonempty trimmed string, maximum 120
Header title Knowledge Base; maximum 80, nonempty after trim; when base key is omitted, falls back to effective base site title
Subtitle Empty; string, maximum 300, empty accepted
Description Documentation and knowledge base; string, maximum 300, empty accepted
Public address Empty; string, maximum 2000, empty accepted; otherwise full HTTP/HTTPS URL
Home hero True; must be an actual boolean

An empty title is refused. An empty subtitle/description/address is accepted. Unknown runtime keys are stripped rather than enabling additional behavior. showHero: "false" is a string and is invalid; use false. Runtime validation is not a universal JSON Schema for every arbitrary file-only customization.

For a nonempty public address, credentials, query and fragment are forbidden. A path is allowed, so a subpath address is valid. The URL is normalized by URL and one trailing slash removed. The public address validation differs from header-link validation: a valid header link may contain query/fragment, but the reader’s site address may not.

Title fallback details

Header-title fallback is computed from base configuration when headerTitle is omitted there. A later runtime override of siteTitle does not automatically rewrite an already effective header title. If you want both labels to change, save both intended values.

siteTitle mainly affects the home hero. With hero off, changing only that field may not visibly change the header or browser-title suffix. Change headerTitle as well when that is your intent. A page’s frontmatter title remains its own title and route input.

A page’s truthy frontmatter description overrides the site default. The default can be an empty string. Descriptions are generated metadata, not a separately indexed search field. Search indexes rendered text/titles/path context, so updating only a description is not a reliable search-query demonstration.

File-only settings

Field Contract
Path prefix baseUrl: empty at domain root; use a reviewed path such as /docs for a subpath
Raw HTML allowRawHtml: enabled only by actual boolean true in file configuration
Copyright copyrightText: available template replacement; stock reader template has no footer displaying it

The Admin safe override mechanism cannot change these policies. Putting them into site-settings.json does not enable them. baseUrl and copyright text do not receive the safe branding field validation. Use intended strings and inspect the output; do not invent a validated path/URL guarantee for them.

The builder escapes supported replacement text in HTML. That does not make globally enabled authored raw HTML safe. Raw HTML permits active content/resources in the finished reader, subject to browser and hosting policy. Every writer and imported document must be trusted if you enable it. The editor preview has a separate sandbox; a safe-looking preview does not prove the static output is harmless.

Subpath hosting

For https://docs.example.com/docs/, use this pair in file configuration:

{
  "siteUrl": "https://docs.example.com/docs",
  "baseUrl": "/docs"
}

This is a fragment showing two fields, not an instruction to erase the rest of the file. The generated furniture/assets use the path prefix; generated Open Graph URLs join site address to page paths. siteUrl is not a substitute for baseUrl.

Authored Markdown URLs are not automatically rewritten. At this subpath, a domain-root /images/tool.png points outside /docs; author the intended /docs/images/tool.png or a reviewed relative URL. Page links must use actual title-derived routes and heading anchors. Test home, deep reload, CSS, fonts, diagrams, search fetch/results, media, downloads and 404 at the real hosted path. Moving a root build under a folder without rebuilding does not correct its generated URLs.

Runtime save, conflicts and malformed files

Admin General/Appearance saves only the safe fields. The server reads the current runtime file and returns an effective settings object plus a revision. The revision is SHA-256 of stored file bytes, or the literal missing marker when no file exists. It protects a settings save from blindly overwriting a file changed since it was loaded.

Outcome Meaning and response
Save succeeds Selected validated object replaces runtime override file through temporary-file rename; rebuild/publish still required
Stale revision 409 Settings changed since load; preserve intended edits, reload current values, review and reapply
Invalid field Fix displayed type/length/address error; rejected input does not save
Broken runtime JSON Read/build can fail; repair or restore private file using source/backup evidence
Broken base JSON Builder warns and uses defaults; do not mistake the fallback site for successful intended configuration

Runtime writes create directories as needed and new files with mode 640. Existing directory/ownership/ACL permissions remain an operator responsibility. Runtime save validates its supplied object; it is not a merge of arbitrary unknown keys into a previously stored file. Omitted safe fields no longer appear in that saved override object and fall back to the effective base/default layer.

Do not delete a damaged runtime file simply to suppress an error before checking what branding it held. Keep the error, selected data path and a recoverable copy, then restore or repair the intended values. Never expose private account files while troubleshooting branding.

Watch, publish and deployed output

Watch monitors content, static assets and templates. It does not watch configuration/runtime-data paths, and configuration is loaded before watched rebuilds. After file configuration changes, stop/restart watch or run a new explicit build process. A later unrelated watched content change is not proof that freshly edited configuration was read.

After runtime settings save, an administrator publication snapshots selected settings for that build. File configuration, templates and static assets are not part of that snapshot; coordinate operator edits while publication is running. A successful local publication still does not upload to Git or a remote host. See Publishing stages and Save publish and deploy.

Configuration acceptance checklist

  1. Confirm checkout, config file, content tree, data selection and intended output.
  2. Verify valid JSON and exact field types. Record any runtime overrides taking precedence.
  3. Start a new build process and inspect its exit/result, not just a browser refresh.
  4. Inspect labels, hero choice, description metadata and site-address/path pair on home and a deep page.
  5. Test served assets, search results, media and links at the target root/subpath.
  6. Review audience and upload only the checked reader output.
  7. Verify the same behavior on the actual deployed host and keep the previous checked output for recovery.

The parser/validation/escaping behaviors are covered by pinned source and regression tests. Actual DNS/TLS/provider deployment and every possible custom template remain checks for your environment. See Environment variables, Frontmatter and Storage and formats for adjacent contracts.