site.yaml
Every key of config/sites/<key>/site.yaml: the site name, hosts, country, time zone, locales and URL strategy, navigation slots, template roots, SEO and robots, accessibility statement, widgets, headless delivery, assets, mail sender and outbound links.
Each directory under config/sites/ is a site, named by its key (lower case letters, digits and hyphens). Its site.yaml holds the site’s identity, hosts, locales, navigation slots, SEO and delivery; its routes.yaml holds the URLs. A site may also have endpoints.yaml, images.yaml, plugins.yaml, promotions.yaml, portal.yaml and its own schema/.
site:
name: { en-GB: Wyndmouth }
timezone: Europe/London
country: GB
default_currency: GBP
domains: [www.wyndmouth.example]
default: true
templates:
roots: [wyndmouth, _shared]
locales:
strategy: prefix
enabled: [en-GB, fr-FR]
default: en-GB
seo:
title_template: "{{ title }} | {{ site.name }}"
sitemap: { enabled: true }
robots: { enabled: true, disallow: ["/studio"] } engine-dmo dev site add writes a new site’s directory with its id. See Sites, locales and routes.
| Key | Type | Default | Meaning |
|---|---|---|---|
accessibility.alt_fallback | string | warn | What publishing does when an image’s alt text would show from a fallback locale: allow, warn or block |
accessibility.alt_fallback_locales | map of string | Per locale, the policy for alt text shown from a fallback locale | |
accessibility.conformance | string | The standard claimed, such as WCAG 2.2 AA | |
accessibility.contact_email | string | Where accessibility problems are reported | |
accessibility.last_reviewed | string | When the statement was last reviewed | |
accessibility.statement_path | string | The path of the site’s accessibility statement | |
assets.budgets | map of string | Size budgets by kind (css, js, legacy_css, legacy_js), each the total across the site’s bundles, such as 120KB | |
assets.bundles | map of string | main: src/entries/<site>.js | The site’s entries by bundle name, each a path relative to the project. Another name defaults to src/entries/<site>-<name>.js |
assets.external | boolean | false | The site is built by a toolchain of its own: the Vite integration builds no entry for it and the asset helpers read assets.manifest |
assets.manifest | string | public/build/.vite/manifest.json | A Vite manifest, relative to the project, for an external site |
delivery.frontend.origin | string | For a headless site, the frontend’s origin; every canonical and absolute URL is built on it. https in production | |
delivery.frontend.preview_url | string | The frontend’s preview route, with {token}, and optionally {path}, {document} and {locale}. https in production | |
delivery.frontend.webhooks | list of objects | [] | Receivers told what changed, so the frontend can revalidate |
delivery.frontend.webhooks[].events | list of string | Every event | The change events to send |
delivery.frontend.webhooks[].secret | string | Required | A secret of at least 16 characters, as ${VAR}, the deliveries are signed with |
delivery.frontend.webhooks[].url | string | Required | The frontend’s revalidation route; https in production |
delivery.mode | string | rendered | rendered (the engine renders pages) or headless (a separate frontend reads the content API) |
embed.enabled | boolean | false | Serve the embeddable widgets under server.embed_path |
embed.map.attribution | string | The tile credit. Required with tiles | |
embed.map.max_zoom | integer | 16 | The map widget’s highest zoom |
embed.map.tiles | string | A tile URL template for the map widget, such as https://tiles.example.org/{z}/{x}/{y}.png. Without it the map is drawn from its markers alone | |
embed.max_items | integer | Caps every list widget, whatever a caller asks for | |
embed.only | boolean | false | Embed-only mode: every page the site serves carries noindex, because the content ranks on the website that embeds it |
embed.origins | list of string | [] | The origins allowed to embed the widgets by script tag or frame |
embed.theme | map of string | {} | CSS custom properties the widget shell sets, so a widget matches the page it sits on |
links.outbound.new_tab | boolean | false | Open links to other websites in a new tab, announced as such, with noopener |
links.outbound.rel | list of string | [] | rel tokens every link to another website carries, such as nofollow |
locales.default | string | Required | The site’s default locale |
locales.domains | map of string | With strategy: domain, the host of each locale | |
locales.enabled | list of string | Required | The locale codes the site runs, from locales.yaml |
locales.fallback | map of list of string | {} | Per locale, the locales whose text shows where it has none, overriding the install’s fallbacks for this site |
locales.strategy | domain, prefix, prefix-all | prefix | How a locale shows in URLs: prefix (every locale but the default under /<code>/), prefix-all (every locale prefixed) or domain (a host per locale) |
mail.from | string | mail.from | The site’s transactional sender |
mail.newsletter.dkim_selectors | list of string | newsletter.dkim_selectors | The DKIM selectors checked for the site’s sending domain |
mail.newsletter.from_address | string | newsletter.from_address | The site’s own newsletter sender address |
mail.newsletter.from_name | string | newsletter.from_name | The site’s own sender name |
mail.newsletter.reply_to | string | newsletter.reply_to | The site’s own reply address |
mail.reply_to | string | mail.reply_to | The site’s Reply-To |
memberships.tiers | list of string | Every tier | The tiers this site sells (engine-dmo) |
nav | map of any | {} | The navigation slots the templates print, by name, each { id, label, depth }. The items are edited in the admin |
seo.default_image | string | The social sharing image used when a page has none | |
seo.robots.agents | list of objects | Groups for named crawlers, written after the group for every crawler: a crawler that finds its name obeys only its own group | |
seo.robots.agents[].allow | list of string | Paths this crawler may fetch | |
seo.robots.agents[].disallow | list of string | Paths this crawler may not fetch | |
seo.robots.agents[].user_agent | string | Required | The crawler’s name |
seo.robots.allow | list of string | Paths reopened under a disallowed one, for every crawler | |
seo.robots.disallow | list of string | Paths no crawler may fetch | |
seo.robots.enabled | boolean | Serve /robots.txt from these rules | |
seo.sitemap | map of any | The sitemap: enabled, max_urls_per_file | |
seo.structured_data.breadcrumbs | boolean | true | Emit a BreadcrumbList from the real URL hierarchy |
seo.structured_data.organisation | any | true | The destination as the publisher of the site: true, false, or a mapping with its type, logo and other properties |
seo.structured_data.search | boolean | true | Emit the WebSite search action where the site routes search |
seo.title_template | string | The page title pattern, such as `“{{ title }} \ | |
settings | map of any | {} | Free values your templates read as site.settings |
site | object | Required | The site itself |
site.country | string | The site’s ISO 3166 country code, which decides country conventions (address formats, the financial year) | |
site.default | boolean | false | The install’s default site. Exactly one |
site.default_currency | string | The site’s ISO 4217 currency | |
site.domains | list of string | Required | The host names the site answers on, with a port where one is used (localhost:8080). *.example.org matches subdomains. A host belongs to one site |
site.id | string | Written for you | The element’s stable id. Written by engine-dmo check --fix; never write or change it by hand |
site.name | map of string | Required | The site’s name per locale |
site.network | string | The default network | The network the site belongs to (networks.yaml) |
site.organisation | string | The organisation that runs the site, for structured data and statements | |
site.path_prefix | string | A path the whole site lives under on its host | |
site.position | integer | The site’s order in the admin | |
site.short_name | map of string | A shorter name per locale | |
site.timezone | string | The site’s IANA time zone | |
templates.allow_unescaped | boolean | false | Allow {% autoescape off %} and the safe filter in this site’s templates |
templates.roots | list of string | [<site>, _shared] | The template directories searched, in order |
networks.yaml and memberships.yaml
Every key of config/networks.yaml (sites sharing organisations, people and partner accounts) and config/memberships.yaml (the membership tiers, engine-dmo).
routes.yaml
Every key of config/sites/<key>/routes.yaml: routes with their URI patterns per locale, index pages, nesting, pagination, facets, feeds, calendars and landing pages, the home page, configuration redirects and special pages.