Content repo
Everything about your site is a file in one repo. Here's the layout, and what each file does.
Layout
site.yaml site settings (admin UI: Settings)
posts/2026-09-30-hello.md → /posts/hello/
posts/2026-10-01-trip/ bundle: index.md plus images served next to the post
pages/about.md → /about/
authors/<login>.md public author profile → /authors/<login>/
assets/ served as-is at /assets/
.trunkcms/users.yaml roles for people without repo access
themes/<name>/ optional selectable themes
theme/ optional site-specific overrides
Pages can be nested: pages/docs/themes.md is served at /docs/themes/. The content repo is always separate from the engine, so one image can serve any content repo.
Front matter
Posts use YAML front matter. The admin UI edits these as form fields and writes them back in a stable order, so diffs stay clean.
---
title: Hello, world
date: 2026-09-30T09:00:00Z
slug: hello-world # optional, derived from the filename
tags: [go, meta]
author: alice-gh # GitHub login; set automatically to the creator
summary: Optional excerpt
draft: false
---
Drafts and scheduled posts
draft: true keeps a post out of index pages, tag pages, feeds and the sitemap. Signed-in users who may view it get the draft at its real URL with a banner, served with Cache-Control: private, no-store. Anonymous visitors get the normal 404, exactly the same as a post that doesn’t exist.
Posts with a future date stay hidden until that time. The sync loop rebuilds when the next scheduled post comes due, so scheduling works without cron.
site.yaml
title: My Blog
description: Notes on things
base_url: https://blog.example.com
language: en
author: { name: Jane Doe, email: jane@example.com }
posts_per_page: 10
permalink: /posts/:slug/ # also supports :year, :month, :day
nav:
- { title: About, url: /about/ }
feeds: { rss: true, atom: true }
theme: { name: paper } # a themes/ dir; empty = the built-in theme
Keys trunkcms doesn’t know about are kept when settings are saved from the UI, so themes can read their own options. This site’s docs sidebar is a docs: list in site.yaml.
Author profiles
An author profile, authors/<login>.md, is public content rendered like a page:
---
name: Alice Example
avatar: /assets/authors/alice.jpg # optional; defaults to the GitHub avatar
links:
- { title: Website, url: https://alice.example }
---
Alice writes about distributed systems and sourdough.
The author: field on a post links its byline to /authors/<login>/, which lists that author’s posts. If there’s no profile, the byline falls back to the login.
Markdown
Rendering uses goldmark with GFM, footnotes, heading IDs and typographic quotes, plus Chroma syntax highlighting with CSS classes. Pages always render raw HTML, since only editors and admins can change them. Posts and profiles use safe mode unless site.yaml sets markdown.unsafe_html: true.