Foundry in one page
Foundry is a Markdown-first CMS written in Go. It keeps content file-based, rendering theme-driven, plugins explicit, and rebuild planning dependency-aware.
Core ideas
- Content lives in Markdown files with frontmatter.
- Routes are assigned from structured content and language-aware conventions.
- Themes own presentation through layouts and partials.
- Themes also own advanced custom-field contracts through
theme.yaml. - Plugins extend behavior through explicit hook interfaces.
- A dependency graph supports incremental rebuilds for both documents and taxonomy archive outputs.
Advanced custom fields are no longer declared in content/config/site.yaml.
Themes declare field contracts in theme.yaml, page-specific values stay in
frontmatter under fields:, and shared/global values live in
content/custom-fields.yaml.
Key directories
/content pages, posts, images, assets, uploads, config
/data structured data files exposed to rendering
/themes active theme layouts and assets
/plugins installed plugins
/public generated output
/docs GitHub Pages content and generated coverage output
Foundry ships two Docker shapes. The default
docker-compose.yml is local-development oriented: it bind-mounts the
project root and keeps data/ and public/ on named Docker
volumes. The stricter docker-compose.prod.yml uses an immutable-style
runtime with required secrets, a read-only root filesystem, a tmpfs for
/tmp, and named volumes for content, themes, plugins, data, and public
output.
Docker start
For local Docker development:
sh scripts/docker-init.sh
docker compose up -d --build
That bootstraps a local .env file with random Docker secrets if one does
not already exist.
For the stricter production-oriented Docker shape:
export FOUNDRY_ADMIN_SESSION_SECRET="$(openssl rand -hex 32)"
export FOUNDRY_ADMIN_TOTP_SECRET_KEY="$(openssl rand -base64 32)"
docker compose -f docker-compose.prod.yml up -d --build
Before using the production Docker overlay, update
content/config/site.docker.prod.yaml so base_url matches
the deployed HTTPS origin.
Common commands
foundry
foundry version
foundry build
foundry build --preview
foundry build --env preview --target production
foundry serve
foundry serve --debug
foundry serve-standalone
foundry serve-preview
foundry status
foundry restart
foundry stop
foundry logs -f
foundry service install
foundry service status
foundry service restart
foundry service uninstall
foundry release cut v1.3.3
foundry update check
foundry update apply
foundry plugin list --enabled
foundry theme list
foundry theme migrate field-contracts
foundry routes check
foundry admin hash-password your-password
If you want additional logging, run foundry serve --debug to log request
timing, slow-render warnings, memory snapshots, goroutine counts, active request counts,
connections, and process CPU time deltas. If admin.debug.pprof is enabled,
the admin Debug page also surfaces runtime, content, storage, integrity, activity, and
persisted build-report snapshots alongside authenticated pprof links.
If you want Foundry to keep running after the terminal closes, use
foundry serve-standalone. Manage that background runtime with
foundry status, foundry restart,
foundry stop, foundry logs -f, and
foundry update check. Foundry stores its runtime files under
.foundry/run/ in the project root. If you launch standalone
from source with go run, Foundry first builds a managed binary
under that directory and keeps the managed binary running.
For a more durable self-hosted runtime, use
foundry service install. That installs Foundry as a user-level OS
service: systemd --user on Linux or a LaunchAgent on macOS. You can
then manage it with foundry service status,
foundry service restart, and foundry service uninstall.
Live reload supports two transport modes: stream uses Server-Sent-Events
(sse) and is the default. poll checks a lightweight endpoint every 1.5
seconds and is the safer choice if your browser hits local connection limits while
reloading.
Media files now live under dedicated collection roots such as
content/images, content/videos, content/audio,
and content/documents. Reference them from Markdown with the
media: scheme, for example ,
,
, or
[Spec PDF](media:documents/spec.pdf). Static builds also write a frontend
search index to public/search.json, and preview builds write
public/preview-links.json.
Important config groups
-
Admin:
admin.pathcontrols the mount point for the themeable admin shell and defaults to/__admin; username/password login is backed bycontent/config/admin-users.yaml, browser sessions expire after 30 minutes of inactivity by default, and the default admin theme includes structured frontmatter editing, restore-preview workflows, media replacement, audit log browsing, user-security flows, a command palette, and keyboard shortcuts. -
Security:
security.allow_unsafe_htmlcontrols whether raw HTML is preserved in Markdown output. -
Server: preview/admin serving uses read, write, and idle timeouts by
default, and live reload can run in
streamorpollmode. -
Deploy:
deploy.targetscan override base URL, public dir, theme, preview mode, and related output settings;foundry build --env <name>also layerssite.<name>.yamlover the base config when present, anddeploy.default_targetis applied automatically when no explicit--targetis passed. - Taxonomies: default and custom taxonomies participate in rendering and incremental rebuild planning.
- Plugins: enabled plugins are validated and synced into generated registration code.
-
Themes: themes must satisfy the minimum slot contract validated by
foundry theme validate.
For the full key-by-key config reference, including all defaults and the exact meaning of each entry, see the Configuration guide.
Operations commands
-
foundry doctorreports timing breakdowns for plugin config, graph load, route assignment, route hooks, asset sync, renderer, and feed generation. -
foundry validatechecks broken links, brokenmedia:references, missing templates, orphaned media, duplicate routes/slugs, and taxonomy inconsistencies. -
foundry backup createandfoundry backup listmanage zip snapshots of the content tree, whilefoundry content export,foundry content import, andfoundry content migratecover portability and schema/layout migration workflows, including--dry-runsupport for layout and field-rename migrations.
Backup workflow
Foundry keeps backup archives simple and portable. The default backup target is
.foundry/backups, and each managed backup is a zip file containing the
current content/ tree plus a small manifest entry.
foundry backup create
foundry backup create ./archives/pre-launch.zip
foundry backup list
foundry backup git-snapshot "before launch"
foundry backup git-log 10
You can also enable debounced automatic backups during
foundry serve or foundry serve-preview:
backup:
enabled: true
dir: ".foundry/backups"
on_change: true
debounce_seconds: 45
retention_count: 20
min_free_mb: 256
headroom_percent: 125
Before Foundry writes a backup archive, it checks free disk space on the destination filesystem and fails early if the archive would not have enough headroom.
Foundry also keeps a local Git-backed snapshot history under
.foundry/backups/git. That path is intended for versioned local history;
it does not push to a remote Git provider yet.
Release updates
Foundry can check GitHub Releases and, for managed standalone installs, apply the latest release automatically:
foundry update check
foundry update apply
Self-update is intentionally limited to serve-standalone deployments.
Docker and source installs still get update availability and release notes, but the
actual rollout remains manual.
Version tags in this repository also trigger a GitHub Actions release workflow that
publishes foundry-*.tar.gz archives and matching .sha256
files for supported platforms.
To cut a release locally, run foundry release cut v1.3.3 from the
repository root. Add --push to push the tag immediately, or use
scripts/release.sh v1.3.3 --push as a repo-local wrapper around the same
command. Foundry requires a clean worktree and a vX.Y.Z version string.
Admin shortcuts
Cmd/Ctrl+Ssaves the current form.Cmd/Ctrl+Enterpreviews the current document.Cmd/Ctrl+Kopens the command palette.Shift+/toggles shortcut help.-
g d,g m,g u, andg ajump to Documents, Media, Users, and Audit.
Recommended reading order
- Read the architecture guide to understand the package layout and runtime flow.
-
Use the configuration reference when you need the exact
meaning or default for a
site.yamlsetting. - Read the plugin guide or theme guide before extending those surfaces.
- Read the CLI contract before changing command UX.
- Open the coverage report if you want to see where tests are still thin.
