codocation.yml
The project configuration file lives at the project root. It contains project-global settings,
the site registry, and the authoritative locale registry. Locale-owned authored and published
pages, trees, images, attachments, definitions, and sidecars live below content/<locale>/.
sites:
cdc: # site id: lowercase letters, digits, dashes
type: docs # docs (default) | blog
locales: [en, de] # variants published by this site
defaultLocale: en # unprefixed routes and fallback source
publicUrl: https://codocation.com
basePath: /docs # omit for the domain root
homeUrl: https://codocation.com # omit to link the title to this site's root
web:
branding:
logo: images/branding/logo.svg # locale-owned; resolved with the page locale
favicon: assets/media/favicon.ico # global, non-localized browser chrome
font: assets/fonts/Inter.woff2 # global web font file
themeColor: "#0b6"
customization:
css: assets/css/site.css # global site CSS
js: assets/js/site.js # global site JavaScript
analytics:
enabled: true
provider: plausible # plausible | ga4
id: codocation.com
ai:
llmsTxt: true
llmsFullTxt: true
pageMarkdown: true
listing:
perPage: 10 # cards per pagination page: posts feed and archives
feed:
enabled: true
limit: 20
fullText: false
links:
externalLinksNewTab: true
internalLinkPreview: true # hover previews on links to published pages
contributeUrl: https://github.com/org/repo/edit/main/docs/
markdownActions: true # "Copy for LLM" and "View as Markdown" on each page
locales:
en:
title: English
de:
title: Deutsch
publicUrl: https://codocation.com # root fallback for sites without their own URL
pdf:
titlePage:
enabled: true
logo: images/pdf/logo.png # locale-owned; resolved with the page locale
font: assets/fonts/Inter.ttf # global PDF font
orientation: portrait
tableOfContents:
enabled: true
pageNumbers:
enabled: true
position: bottom-center
build:
output: dist
cleanUrls: true
Notes
- Locale catalog: root
localesis the canonical project-wide catalog. Each entry owns the locale code, order, and displaytitle; catalog membership is the strict union of all site memberships, so inactive catalog entries are invalid. - Site variants:
sites.<siteId>.localeslists the variants that site publishes. A requiredcontent/<locale>/<siteId>.tree.ymland optional sidecars exist only for declared pairs. An undeclared pair file is an ERROR and ignored; acontent/<unknown-locale>/directory is an orphan-locale ERROR and ignored. - Site default:
sites.<siteId>.defaultLocaleowns the site's unprefixed route and the page, localized-definition, SEO, and PDF fallback. A one-locale site may omit it (the sole member is effective); a site with multiple locales must name exactly one member explicitly. - Presentation metadata: required
titleand optionaldescriptionlive at the root ofcontent/<locale>/<siteId>.tree.yml, next toheader,toc, andfooter. - Global technical assets: every configured global resource must use one of the enforced
namespaces
assets/media/,assets/fonts/,assets/css/, orassets/js/. There are no locale-specific favicon, font binaries, CSS, JavaScript, or analytics files in this layout. - Per-site web overrides: a site entry may carry its own
web:block; its explicit values override matching global fields. Web has Global and Per-site scopes, never a Locale scope. - Outbound links:
web.links.externalLinksNewTabgoverns every external (http/https) link the site renders, including header entries, landing buttons, and page body links; the default istrue.web.links.contributeUrlnames the folder holdingcodocation.ymlin a repository; each page's own source path is appended to it to build an "Edit this page" link (see Titles, URLs, and Branding).web.links.internalLinkPreview(defaulttrue) decides whether a link to a published page carries its target's title and annotation for a hover preview.web.links.markdownActions(defaulttrue) shows "Copy for LLM" and "View as Markdown" in each page's article meta row. All four merge likeweb.branding: a site's own value overrides the matching global field. A site opts a globally-authoredcontributeUrlback out for itself by setting its ownweb.links.contributeUrlto an empty string. - Listing size:
web.listing.perPage(default 10) is the number of cards on one pagination page - the posts feed and every tag or category archive alike. - RSS feed:
web.feedcan be set globally or under a site'swebblock. It carriesenabled,limit, andfullText; see RSS Feeds for the stream dates, item identity, and output path. - Deployments:
codocation.ymlhas no deployment section. Named deployment groups live in project-rootdeployments.yml; tokens stay in the IDE password safe. - Locale sidecars: optional files sit beside the tree:
content/<locale>/<siteId>.pdf.yml,<siteId>.seo.yml, and<siteId>.redirects.yml. SEO resolves requested locale →sites.<siteId>.defaultLocale→ built-in defaults. PDF resolves requested locale →sites.<siteId>.defaultLocale→sites.<siteId>.pdf→ globalpdf→ built-in defaults. Each sidecar merges presence-aware leaves; a present leaf replaces the lower layer wholesale, with no deep or list merging. Redirects use only the requested locale and absence means an empty set. - Fallback source: locale-aware images and attachments resolve using the page's source provenance. A page resolved from the default language and shown in another uses the source locale's media, so an English source page cannot accidentally use a German download.
- Pages have no marker: a page's text follows its own file, resolving from the requested locale when that file exists and from the site's effective default otherwise.
- Classifier marker: a label or category entry made of
inherited: truealone takes the whole payload from the current site's effective default. Without it, an omitted classifier identity stays unavailable in that locale.
Scope visibility and writes
- PDF exposes Global, Per-site, and Locale targets. Per-site is shown when the project has
more than one site or
sites.<siteId>.pdfalready contains an explicit override. Locale is shown when the project has more than one locale or the requested locale's<siteId>.pdf.ymlalready exists. A single-site, single-locale project with neither override edits the global section directly, without a selector. - Web and Output expose only Global and Per-site targets. Per-site is shown for a
multi-site project or when the current site's
weborbuildsection already contains an explicit override. These scopes never receive a Locale target. - SEO and Redirects have no scope selector: they have no global or per-site layer outside the selected locale sidecars. Their write target is always the current site and requested locale. SEO displays the requested-locale → site-default → built-in effective value, but edits create or change only a sparse requested-locale override; resetting a leaf deletes only that override and restores fallback.
- SEO
metaTagsis one list-valued leaf. Lists never merge by element, so the first edit to an inherited row materializes the complete effective list in the requested-locale sidecar before applying the row change. ResettingmetaTagsremoves that whole requested leaf. - Redirects read and write only the requested-locale file. Resetting redirects deletes that file or leaves the requested redirect set empty.
- Locale PDF writes target the requested locale's PDF sidecar. For a non-default requested locale they never write the site-default sidecar; the site default's own sidecar is its legitimate target. Reset on any layer deletes only that layer's override, and switching scope never moves configuration between layers.
deployments.yml
Named deployment groups are stored separately from content and presentation configuration:
deployments:
production:
name: Production documentation
sites:
- cdc
provider: cloudflare-pages
accountId: <account id>
project: codocation
github-mirror:
name: GitHub mirror
sites:
- cdc
provider: github-pages
repository: company/documentation
branch: gh-pages
path: docs/
Each group has a stable mapping key, a visible name, and at least one site ID. Cloudflare Pages
groups identify an account and project. GitHub Pages groups identify a repository and branch, with
an optional publish path. A site may belong to more than one group. Two groups cannot target the
same normalized destination, and their selected sites must not collide in the generated snapshot.
