Settings

Every setting in sitemd lives in a markdown file with YAML frontmatter. Edit the file, save, and your site rebuilds with the new values.

# settings/meta.md
---
title: My Site
url: https://example.com
description: A site built with sitemd
---

Settings files are in your settings/ directory, tracked in git, and readable by humans and AI agents alike. The only exception is secrets (API keys, tokens, passwords) — those are stored separately in .sitemd/config.json and never committed.

Settings files

File What it controls
meta.md Site title, URL, description, favicon
header.md Brand display, navigation items, search, theme toggle, auth button
footer.md Footer links, copyright, tagline, social icons
theme.md Color palette, dark/light mode, border radius, fonts
groups.md Page groups for sidebars, header dropdowns, footer columns
build.md Build pages list, output directory
seo.md Language, OG images, structured data, robots, IndexNow
deploy.md Domain, deploy target, provider settings, media hosting
email.md Email provider, sender address, SMTP settings
analytics.md Analytics provider, tracking ID, GTM, custom head
auth.md Auth provider, login mode, redirects, provider URLs
data.md Data provider, cache TTL, data sources, provider URLs
forms.md Default submit label, thank-you message, honeypot

The 9 core files (meta, header, footer, theme, groups, build, seo, deploy, data) ship with the scratch template. The remaining files (email, analytics, auth, forms) are created when you enable those features — via sitemd config setup, the MCP setup tools, or by creating the file manually. Run sitemd init or call sitemd_init to scaffold a new project with the core files.

How settings work

Every settings file follows the same pattern: YAML key-value pairs between --- delimiters. Comments starting with # are documentation — the build engine ignores them.

# settings/deploy.md
---
# Deploy target: cloudflare, github, netlify, vercel
target: cloudflare

# Cloudflare Pages project name
cloudflareProject: my-site

# ── Secrets (CLI-managed) ─────────────────────────
# Manage secrets: sitemd config setup deploy
# cloudflareApiToken: ...8759
---

Three kinds of lines:

  1. Active settingskey: value lines that the build engine reads
  2. Comments — lines starting with # that document what each setting does
  3. Commented-out settings# key: value lines showing available options with defaults

To enable a commented-out setting, remove the # and set your value.

Two-tier architecture

Settings are split into two tiers based on sensitivity:

Settings files (settings/*.md) Config store (.sitemd/config.json)
Contains Everything you'd put in source control API keys, tokens, passwords
Edited by You, directly in the file sitemd config set or sitemd config setup
Tracked in git Yes No (gitignored)
Examples Provider names, project IDs, URLs, domains, UI preferences Cloudflare API token, email API key, Supabase anon key

The rule: if it's safe to commit to git, it belongs in a settings file. If it's a secret, it belongs in the config store.

The secrets mirror block

Settings files that have associated secrets show a mirror block at the bottom:

# ── Secrets (CLI-managed) ─────────────────────────
# Manage secrets: sitemd config setup deploy
# cloudflareApiToken: ...8759

This block is read-only — the build engine writes it on every build to show which secrets are configured. The values are redacted (only the last 4 characters shown). To change a secret, run the command shown in the block or use sitemd config set.

Edit anything above the mirror block. The mirror block itself is overwritten on every build.

Build precedence

When the same value exists in multiple places:

  1. Environment variables — highest precedence (for CI)
  2. Config store secrets.sitemd/config.json
  3. Settings filessettings/*.md frontmatter

In practice, you edit settings files for day-to-day changes, use the config store for secrets, and use environment variables only in CI pipelines.

Settings schema

Every settings file has a defined schema of valid keys. The schema is centralized in settings-schema.js — a single source of truth used by the build validator, MCP tools, and agents.

Each file entry in the schema defines:

Retrieving the schema

Agents retrieve the full annotated schema by reading settings/_schema (or calling the MCP settings tool with name: "_schema"):

{ "name": "_schema" }

The response includes a _guide explaining the two-tier pattern, then every settings file with per-key metadata:

{
  "_guide": "Settings live in two places: settings/*.md for non-secret config...",
  "deploy.md": {
    "required": [],
    "keys": {
      "target": { "validValues": ["cloudflare", "github", "netlify", "vercel"] },
      "cloudflareProject": { "label": "Cloudflare Pages project name", "secret": false },
      "cloudflareApiToken": {
        "label": "Cloudflare API token",
        "secret": true,
        "setVia": "sitemd_config_set",
        "configKey": "deploy.cloudflareApiToken"
      }
    }
  }
}

Each key includes:

Field Meaning
label Human-readable description
secret true if the value is a secret — must use sitemd_config_set, never write to settings files
setVia Which tool to use (sitemd_config_set for secrets)
configKey The dot-path key to pass to sitemd_config_set (included when it differs from the obvious file.key pattern)
validValues Array of allowed values for constrained keys

Keys with an empty object {} are simple non-secret settings — edit them directly in the settings file.

Key reference

File Required Known keys
meta.md title title, brandName, description, url, brandImage, favicon, customFavicon, titleSuffix, tabTitle, tabTitleSuffix
header.md brandDisplay, brandName, themeModeToggle, search, headerAuth, items
footer.md copyright, brandName, brandDisplay, tagline, items, social
theme.md defaultMode, accentColor, fontSans, fontMono, contentWidth, pageWidth, radius, imageCorners, borderRadius, buttonStyle
build.md port, pagesDir, themeDir, outputDir, sitemap, robots, imageOptimization, imageMaxWidth, imageQuality
deploy.md target, cloudflareProject, cloudflareAccountId, cloudflareBranch, netlifySiteId, vercelProjectId, vercelTeamId, githubRepo, githubBranch, mediaHosting, mediaCdnUrl, r2AccountId, r2Bucket, s3Region, s3Bucket, deployPages, additionalDomains
seo.md language, ogImage, ogStyle, ogBackground, ogTextColor, ogLogo, defaultAuthor, twitterHandle, structuredData, llmsTxt, markdownOutput, allowAICrawlers, indexNow, orgName, orgLogo
email.md provider, from, host, port, user, region
analytics.md provider, id, host, gtm, pixels, customHead
auth.md provider, loginMode, loginPage, afterLogin, afterLogout, userDataUrl, userTypeField, accessDeniedPage, apiUrl, supabaseUrl, firebaseAuthDomain, firebaseProjectId, auth0Domain, auth0ClientId
data.md provider, cacheTTL, loadingText, emptyText, errorText, supabaseUrl, firebaseProjectId, airtableBaseId, restBaseUrl, sources
forms.md submitLabel, thankYou, honeypot, countrySortToTop
groups.md groups

Keys starting with palette. are always valid in any file — they define custom named colors.

Self-repair

The build engine validates your settings files against the schema on every build. Warnings are non-blocking — your site still builds. They surface three types of issues:

Missing required keys

⚠ meta.md: missing required "title"

The key is required but not present in the file. Add it.

Unknown keys

⚠ meta.md: unknown key "typo" — check spelling or remove

The key isn't recognized in any settings file. Usually a typo.

Misplaced keys

⚠ meta.md: "items" belongs in header.md, not here

The key is valid but in the wrong file. The validator cross-references the schema to tell you exactly where it should go. Move it to the indicated file.

Invalid values

⚠ deploy.md: "target" has invalid value "clouflare" (expected: cloudflare, github, netlify, vercel)

The key has a value that doesn't match the allowed options. Fix the typo or pick from the listed values.

Auto-scaffolding

Beyond settings validation, the build engine also auto-scaffolds missing pages referenced in navigation. If your header.md lists a nav item pointing to /about but pages/about.md doesn't exist, the build creates a placeholder page with the right frontmatter and a content template. This means you can define your navigation structure first, then fill in the content — the build won't break on missing pages.

Editing settings via CLI or MCP

You don't have to edit files by hand. The CLI and MCP server both route values to the right place automatically:

# Sets a secret → goes to .sitemd/config.json
sitemd config set deploy.cloudflareApiToken cf_xxx

# Sets a non-secret → goes to settings/deploy.md frontmatter
sitemd config set deploy.cloudflareProject my-site

The sitemd config setup wizard does this routing automatically — it asks for values, then writes non-secrets to settings files and secrets to the config store.

AI agents do the same thing through MCP:

// Agent calls sitemd_config_set
{ "key": "deploy.cloudflareProject", "value": "my-site" }
// → Written to settings/deploy.md frontmatter

{ "key": "deploy.cloudflareApiToken", "value": "cf_xxx" }
// → Written to .sitemd/config.json

CI environment variables

For CI pipelines, set environment variables instead of editing files. Environment variables take the highest precedence and override both settings files and the config store. See CLI — CI environment variables for the full mapping.

Resetting a settings file

If a settings file gets corrupted or you want to start over, delete it and run sitemd init (or call sitemd_init via MCP) to copy the default from the scratch template. The build engine handles missing settings files gracefully — it uses built-in defaults for anything not specified.