Blueprint format
A blueprint is a YAML or JSON document describing part of a Craft content model. Archie decides
which by looking at the first character: a { or [ means JSON, anything else is parsed as YAML.
The document
archie: 1 # schema version; optional, defaults to 1
name: Blog # shown in the CP and in run history
description: … # optional
vars: # values for {{ placeholders }} below
handle: blog
fields: […] # components, by type
entryTypes: […]
sections: […]
Every other top-level key is a component type. These are the canonical names, in the order an apply runs them:
siteGroups, sites, filesystems, transforms, fields, entryTypes, sections, volumes,
categoryGroups, tagGroups, globalSets, userGroups, routes
Singular spellings work, as do a few natural aliases (globals, categories, tags, fs,
imageTransforms). Unknown keys are ignored with a notice rather than an error, so a document
carrying an extra key from somewhere else still runs.
Components
A component type takes either a list or a handle-keyed mapping. These are the same:
fields:
- handle: summary
type: plainText
fields:
summary:
type: plainText
Every component needs a handle. If you give a name and no handle, one is derived from it; if you
give a handle and no name, the name is derived from that. Deriving is not the same as stating:
a derived value is used when creating a component and ignored when comparing against an existing
one, so a blueprint that never mentions a name will never rename anything.
Blueprints are partial
A blueprint says what should exist and how it should be configured. It does not claim to be a
complete inventory, and Archie only ever compares the keys you actually wrote. A blueprint that says
nothing about searchable is not asking for searchable: false.
A key that the component has no equivalent for — a Craft 4 leftover, or a setting belonging to a different field type — is reported in the plan as ignored rather than treated as a difference, because a difference no apply could resolve is a plan that never comes clean.
Variables
vars:
handle: blog
sections:
- handle: '{{ handle }}'
uriFormat: '{{ handle }}/{slug}'
Supply or override them with --vars="handle=news" on the console, or in the CP's variables box
(one name = value per line). A value that is only a placeholder takes the variable's real type,
so enableVersioning: '{{ live }}' with live: false gives a boolean, not the string "false".
A placeholder nothing supplies a value for is a lint error, not a silent empty string.
References
Everything a blueprint points at is named by handle. Archie translates to UIDs on the way in and back on the way out.
fields:
- handle: relatedPosts
type: entries
settings:
sources: [blog, news] # section handles
- handle: pageBuilder
type: matrix
settings:
entryTypes: [textBlock, imageBlock]
sections:
- handle: blog
entryTypes: [article] # entry type handles
volumes:
- handle: media
fs: media # filesystem handle
The prefixed form (section:blog, volume:media, group:topics) is accepted too, and is what
exports write, since a bare handle is ambiguous once more than one kind of source is possible.
Field types
type takes a shorthand or a full class name:
type: plainText # craft\fields\PlainText
type: matrix # craft\fields\Matrix
type: ckeditor # craft\ckeditor\Field
type: craft\fields\PlainText # always works
Shorthands are derived from the registered classes: the short class name with a redundant Field
suffix removed, falling back to the plugin's namespace segment when the class is called plain
Field. A plugin's field type therefore gets a shorthand the day it is installed. If two plugins
derive the same shorthand, Archie says so and asks for the full class name.
The same applies to filesystem types (local).
Field layouts
Three shapes are accepted, and they mean the same thing:
fieldLayout: [summary, body] # one “Content” tab
fieldLayout: # Architect's tab map
Content: [summary]
SEO: [metaTitle]
fieldLayout: # Archie's own
- name: Content
fields:
- summary # bare handle
- handle: body # or with attributes
required: true
width: 50
label: Article body
instructions: …
- ui: heading # a UI element
heading: SEO
- ui: rule
- native: entryTitle # a native element
UI elements: heading, tip, rule, lineBreak, template, markdown, html.
hasTitleField on an entry type is handled for you. Craft derives it from whether the layout
contains the title element rather than storing what you set, so Archie adds or removes that element
to match what you asked for.
A layout naming a field that does not exist and is not created by the blueprint is a lint error. This matters more than it looks: Craft's own layout builder drops unknown elements without a word, so without the check a typo produces a silently shorter layout and no error anywhere.
Sections
sections:
- handle: blog
name: Blog
type: channel # channel | structure | single
enableVersioning: true
propagationMethod: all
defaultPlacement: end
maxLevels: 3 # structures only
entryTypes: [article]
# Per-site settings, keyed by site handle
siteSettings:
default:
uriFormat: 'blog/{slug}'
template: 'blog/_entry'
enabledByDefault: true
second: false # turn the section off for this site
# …or, for every site at once:
uriFormat: 'blog/{slug}'
template: 'blog/_entry'
The top-level shorthand and the '*' key both mean "every site", and are expanded to per-site
entries before anything is compared. hasUrls is inferred from whether a uriFormat was given.
A site the blueprint does not mention keeps whatever settings it already has.
Routes
routes:
- uri: 'blog/{slug}'
template: 'blog/_entry'
site: default # optional
- uri: 'news/{year:\d{4}}/{slug}'
template: 'news/_entry'
{name} matches Craft's default of [^\/]+; {name:pattern} sets the pattern explicitly.
Filesystems
Credentials do not belong in a blueprint. Use environment variables; Archie warns when a setting whose name looks like a secret holds a literal value.
filesystems:
- handle: media
type: local
hasUrls: true
url: '@web/uploads/media'
settings:
path: '@webroot/uploads/media'
Reading Craft 4 blueprints
Archie reads Architect documents directly. It:
- hoists entry types defined inside a section up to the top level, where Craft 5 keeps them;
- reads the tab-map field layout shape;
- maps
field_type→typeandtypesettings→settings; - drops field groups, which Craft 5 removed, with a notice naming each one;
- drops
titleLabeland other retired keys, with a notice; - strips
id,uid,sortOrderand other keys that only mean something on one install; - rewrites Craft 4 Matrix
blockTypesinto Craft 5 entry types, promoting each block's fields to real fields and pointing the Matrix field at the new entry types by handle.
That last one is the reason a Craft 4 blueprint cannot simply be re-run: the most common thing in it no longer exists. Where a block handle or an inner field handle is already taken at the top level — they only had to be unique within their own field in Craft 4 — Archie qualifies it with the Matrix field's handle and tells you which name it chose.
php craft archie/blueprint/convert old.json --out=new.yaml writes the converted document out so
you can read it before applying it.