Configuration
This page is the canonical reference for Foundry's site config. It explains what each config group is for, what each key does, and where examples are useful it shows the expected YAML shape directly.
What this file does
content/config/site.yaml is the main runtime config for a Foundry site. It
controls site identity, serving, admin behavior, build output, content layout,
taxonomies, plugin activation, deploy targets, feeds, and theme-facing values.
Foundry also supports environment overlays such as
content/config/site.preview.yaml. Those files are layered on top of the
base config when you run commands like foundry build --env preview.
If you want a full explicit config with every current default written out, start from
content/config/example.site.yaml.
How Admin Settings Relate To site.yaml
Foundry keeps content/config/site.yaml as the source of truth on disk,
even when you edit settings through the admin UI.
The admin Settings area uses structured forms because forms are safer and more usable for most changes than editing a raw YAML document directly. Under the hood, the flow is:
- YAML on disk: the persistent project config remains YAML.
- Structured object in memory: the admin loads that YAML into a config object.
- Forms in the UI: the object is presented as inputs, toggles, selects, and section-specific editors.
- Structured save back to YAML: when you save, Foundry validates the structured config and writes it back to
site.yaml.
Some parts of the config surface are naturally scalar and form-friendly. Others, such as taxonomy definitions, field schemas, deploy targets, menus, params, and permalinks, are more deeply nested. Those still live inside the structured Settings area, but they may use JSON-shaped editors in their own tabs rather than trying to force everything into a single giant YAML textarea.
Foundry also keeps an Advanced YAML tab in admin. That exists so advanced users can still edit the raw config directly when they need full manual control or want to work with values that are easier to express in YAML than in a form.
Minimal example
name: "foundry"
title: "Foundry CMS"
base_url: "http://localhost:8080"
theme: "default"
backup:
enabled: false
dir: ".foundry/backups"
server:
addr: ":8080"
live_reload: true
admin:
enabled: true
path: "/__admin"
theme: "default"
content:
pages_dir: "pages"
posts_dir: "posts"
Top-level keys
These keys define the overall site identity and root directory layout.
-
name: machine-oriented site identifier used in status output and metadata. Default:foundry. -
title: human-facing site title. Default:Foundry CMS. -
base_url: canonical site base URL used for absolute links, feeds, preview manifests, and deploy output. Default: empty. -
theme: active frontend theme name underthemes/. Default:default. -
environment: environment label such asdefault,preview, orproduction. Default:default. -
default_lang: default language code for content routing. Default:en. -
content_dir: root content directory. Default:content. -
public_dir: build output directory. Default:public. -
themes_dir: theme root directory. Default:themes. -
data_dir: runtime data directory used for state files and structured data. Default:data. -
plugins_dir: plugin installation directory. Default:plugins.
backup
This group controls zip backups for the content tree and the optional debounced on-change backup flow while the preview server is running.
-
enabled: enables managed backup behavior. Default:false. -
dir: output directory for managed backup archives. Default:.foundry/backups. -
on_change: when true,foundry serveandfoundry serve-previewcreate backups after content changes settle. Default:false. -
debounce_seconds: quiet period before an on-change backup fires. Default:45. -
retention_count: number of backup archives to keep inbackup.dirbefore older ones are pruned. Default:20. -
min_free_mb: minimum safety buffer added to backup free-space checks. Default:256. -
headroom_percent: minimum free-space multiplier relative to the source size before a backup starts. Default:125.
backup:
enabled: true
dir: ".foundry/backups"
on_change: true
debounce_seconds: 45
retention_count: 20
min_free_mb: 256
headroom_percent: 125
Zip backups are the primary export and restore format. Foundry also supports local
Git-backed snapshots via foundry backup git-snapshot and
foundry backup git-log, stored under .foundry/backups/git.
server
This group controls the preview server and live reload behavior.
-
addr: bind address for the preview server. Default::8080. -
live_reload: enables or disables live reload. Default:false. -
live_reload_mode: reload transport. Usestreamfor Server-Sent Events orpollwhen browser connection limits make SSE unreliable. Default:stream. -
auto_open_browser: automatically opens the preview URL after startup. Default:false. -
debug_routes: enables extra debug-only route output where supported. Default:false.
server:
addr: ":8080"
live_reload: true
live_reload_mode: "poll"
auto_open_browser: false
debug_routes: false
admin
This group controls the admin shell, admin auth, persistent session state, and admin-only debug features.
-
enabled: enables or disables the admin surface. Default:false. -
addr: reserved for a separate admin bind address. The current server mounts admin under the main HTTP server. Default: empty. -
path: admin mount path. Default:/__admin. -
local_only: rejects forwarded or non-local admin access when true. Default:false. -
access_token: optional API token for automation or non-browser admin access. Default: empty. -
theme: active admin theme underthemes/admin-themes/. Default:default. -
session_secret: optional secret used when hashing persisted admin session tokens. Set this in production or viaFOUNDRY_ADMIN_SESSION_SECRETso session hashes are keyed with an explicit server secret. Default: empty. -
totp_secret_key: base64-encoded 32-byte key used to encrypt stored TOTP secrets at rest. Set this in production or viaFOUNDRY_ADMIN_TOTP_SECRET_KEY. New TOTP setup requires it. Default: empty. -
users_file: filesystem-backed user database file. Default:content/config/admin-users.yaml. -
session_store_file: persistent session store file. Foundry stores a session token hash there, not the raw reusable bearer token. Default:data/admin/sessions.yaml. -
lock_file: persistent document lock file used by editor locking. Default:data/admin/locks.yaml. -
session_ttl_minutes: idle browser session timeout. Default:30. -
session_idle_timeout_minutes: explicit inactivity timeout for admin sessions. Set to0to disable the separate idle-policy check and rely only on the rolling session TTL. Default:0. -
session_max_age_minutes: absolute maximum admin session lifetime, even if the session remains active. Set to0to disable the cap. Default:0. -
single_session_per_user: when enabled, Foundry revokes older sessions for the same user at login time. Default:false. -
password_min_length: minimum password length for save and reset flows. Default:12. -
password_reset_ttl_minutes: password reset token lifetime. Default:30. -
totp_issuer: issuer string embedded in TOTP setup URIs. Default:Foundry.
admin.debug
-
pprof: enables authenticatednet/http/pprofaccess and the admin Debug page runtime summary. Default:false.
admin:
enabled: true
addr: ""
path: "/__admin"
local_only: false
access_token: ""
session_secret: ""
totp_secret_key: ""
theme: "default"
users_file: "content/config/admin-users.yaml"
session_store_file: "data/admin/sessions.yaml"
lock_file: "data/admin/locks.yaml"
session_ttl_minutes: 30
session_idle_timeout_minutes: 30
session_max_age_minutes: 480
single_session_per_user: false
password_min_length: 12
password_reset_ttl_minutes: 30
totp_issuer: "Foundry"
debug:
pprof: true
Admin security
- Set
admin.session_secretorFOUNDRY_ADMIN_SESSION_SECRETin production. - Without it, Foundry still hashes session tokens at rest, but with plain SHA-256 instead of keyed HMAC-SHA-256.
- Set
admin.totp_secret_keyorFOUNDRY_ADMIN_TOTP_SECRET_KEYin production to encrypt TOTP secrets at rest. - New TOTP setup requires that encryption key. Legacy plaintext TOTP secrets still verify and are migrated to encrypted form when used.
- Admin password hashes now default to
argon2id$.... - Legacy PBKDF2 password hashes still verify and are upgraded automatically on successful login.
- For non-local admin access, set
base_urlto anhttps://origin and make sure your reverse proxy forwards HTTPS correctly soSecurecookies work as intended. - Rotating
admin.session_secretinvalidates all browser sessions. - Rotating
admin.totp_secret_keyrequires TOTP re-enrollment for any still-encrypted secrets that cannot be migrated under the new key. - If either secret is suspected compromised, rotate it, revoke active sessions, and review the audit log before restoring access.
- Compatibility note: legacy plaintext sessions, legacy plaintext TOTP secrets, and legacy PBKDF2 hashes are kept only as a migration bridge and are intended to be removed after the
1.4.xline.
build
This group controls the shape of static build output.
-
clean_public_dir: removespublic/before a build. Default:false. -
include_drafts: includes draft content in build output. Default:false. -
minify_html: minifies rendered HTML. Default:false. -
copy_assets: copies content-owned static assets into output. Default:false. -
copy_images: copies image media into output. Default:false. -
copy_uploads: copies legacy uploads plus the current non-image media collections where applicable. Default:false.
content
This group defines directory names under content/ and a few core content
defaults.
-
pages_dir: page document directory. Default:pages. -
posts_dir: post document directory. Default:posts. -
images_dir: image media directory. Default:images. -
videos_dir: video media directory. Default:videos. -
audio_dir: audio media directory. Default:audio. -
documents_dir: document-like media directory. Default:documents. -
assets_dir: content-owned static asset directory. Default:assets. -
uploads_dir: legacy upload directory retained for compatibility. Default:uploads. -
max_versions_per_file: maximum retained filesystem versions per file before pruning. Default:10. -
default_layout_page: default layout for pages. Default:page. -
default_layout_post: default layout for posts. Default:post. -
default_page_slug_index: slug used for section-index pages. Default:index.
content:
pages_dir: "pages"
posts_dir: "posts"
images_dir: "images"
videos_dir: "videos"
audio_dir: "audio"
documents_dir: "documents"
assets_dir: "assets"
uploads_dir: "uploads"
max_versions_per_file: 10
default_layout_page: "page"
default_layout_post: "post"
default_page_slug_index: "index"
permalinks
This group defines the route templates used when Foundry assigns URLs to pages and posts.
-
page_default: default-language page route pattern. -
page_i18n: non-default-language page route pattern. -
post_default: default-language post route pattern. -
post_i18n: non-default-language post route pattern.
permalinks:
page_Default: "/:slug/"
page_i18n: "/:lang/:slug/"
post_Default: "/posts/:slug/"
post_i18n: "/:lang/posts/:slug/"
taxonomies
This group enables taxonomy rendering and defines which taxonomies exist.
-
enabled: enables taxonomy support. Default:false. -
default_set: taxonomy names enabled by default for content. Default:[tags, categories]. -
definitions: per-taxonomy definitions keyed by taxonomy name. Default:{}.
Each taxonomy definition supports:
-
title: human title for the taxonomy. -
labels: per-language label map. -
archive_layout: optional archive layout override. -
term_layout: layout used for individual term pages. -
order: ordering hint such asalpha.
taxonomies:
enabled: true
default_set:
- tags
- categories
definitions:
tags:
title: "Tags"
labels:
en: "Tags"
es: "Etiquetas"
archive_layout: "list"
term_layout: "list"
order: "alpha"
categories:
title: "Categories"
labels:
en: "Categories"
archive_layout: "list"
term_layout: "list"
plugins
This group controls which installed plugins are enabled for the site.
-
enabled: list of plugin names to enable. Default: empty list.
plugins:
enabled:
- toc
- relatedposts
- readingtime
Advanced Custom Fields
Foundry no longer stores advanced custom-field schemas in
content/config/site.yaml. Advanced fields are now a theme-owned contract.
-
Theme schema: declare field contracts in
theme.yamlunderfield_contracts. -
Page values: keep page-specific values in page frontmatter under
fields:. -
Shared values: store shared/global field values in
content/custom-fields.yaml. - Admin discoverability: the editor resolves applicable fields from the active theme based on document type, layout, and slug.
field_contracts:
- key: marketing-page
title: Marketing Page
target:
scope: document
types: [page]
layouts: [page]
slugs: [pricing, about, contact]
fields:
- name: hero_title
type: text
label: Hero Title
- name: hero_body
type: textarea
label: Hero Body
- key: site_marketing
title: Site Marketing
target:
scope: shared
key: site_marketing
fields:
- name: primary_cta_label
type: text
label: Primary CTA Label
---
title: Pricing
slug: pricing
layout: page
fields:
hero_title: Clear pricing for modern teams
hero_body: Foundry keeps publishing infrastructure calm and predictable.
---
values:
site_marketing:
primary_cta_label: Start with Foundry
If you still have legacy field schemas in site.yaml, migrate them with
foundry theme migrate field-contracts.
seo
This group controls SEO-oriented output defaults.
-
enabled: enables SEO-related handling where supported. Default:false. -
default_title_sep: default title separator when combining page and site titles. Default: empty.
cache
This group controls cache-related behavior where supported by the current runtime.
-
enabled: enables cache-related behavior. Default:false.
security
This group controls security-sensitive rendering behavior.
-
allow_unsafe_html: preserves raw HTML from Markdown when true. Leave thisfalseunless you intentionally trust raw HTML in content. Default:false.
feed
This group controls RSS and sitemap output.
-
rss_path: RSS route path. Default:/rss.xml. -
sitemap_path: sitemap route path. Default:/sitemap.xml. -
rss_limit: maximum number of items in the RSS feed. Default:50. -
rss_title: feed title. Default: the site title. -
rss_description: feed description. Default: the site title.
feed:
rss_path: "/rss.xml"
sitemap_path: "/sitemap.xml"
rss_limit: 50
rss_title: "Foundry CMS"
rss_description: "Foundry CMS"
deploy
This group defines named deploy targets that can override selected config values during builds.
-
default_target: target name to use by default. Default: empty. -
targets: map of named deploy targets. Default:{}.
Each deploy target supports:
-
base_url: override canonical base URL. -
public_dir: override output directory. -
theme: override frontend theme. -
include_drafts: override build draft inclusion. -
environment: override environment label. -
preview: when true, forces preview-style draft inclusion. -
live_reload_mode: override live reload transport for the target.
deploy:
default_target: "production"
targets:
production:
base_url: "https://example.com"
public_dir: "public-prod"
theme: "default"
include_drafts: false
environment: "production"
preview: false
live_reload_mode: "stream"
preview:
base_url: "https://preview.example.com"
public_dir: "public-preview"
include_drafts: true
environment: "preview"
preview: true
live_reload_mode: "poll"
params
This is a free-form map of site-level values exposed to themes, templates, and plugins.
-
params: arbitrary key-value data. Default:{}.
params:
company_name: "Sphire"
support_email: "support@example.com"
home_eyebrow: "Launch Week"
menus
This group defines named menus. Each menu contains items with name and
url.
-
menus: menu map keyed by menu name. Default:{}. -
name: item label shown in the UI. -
url: destination URL.
menus:
main:
- name: "Home"
url: "/"
- name: "Docs"
url: "/docs/"
footer:
- name: "RSS"
url: "/rss.xml"
- name: "GitHub"
url: "https://github.com/sphireinc/foundry"
Defaults and examples
-
Use
content/config/example.site.yamlwhen you want every current default spelled out explicitly. -
Keep
content/config/site.yamlfocused on the values you are actually overriding. -
Use overlays like
content/config/site.preview.yamlor named deploy targets when a setting should only change for preview or production builds. -
When a group contains nested structures like
taxonomies.definitions, ordeploy.targets, prefer full YAML snippets over terse one-line docs so the expected shape stays obvious. For advanced custom fields, define the contract intheme.yamland keep shared values incontent/custom-fields.yaml.
