Guide 04 · Developer docs

Input types, layouts, components and images

The platform's central abstraction, in one line: an input type defines what an editor can enter, a layout area binds one input type to a named slot, a layout groups areas and points at a template, a record or component holds the content for each area, and the template reads it back. Read this book straight after the template languages.

L1–L3
Unit 09 · Patterns, live preview and upkeep

Naming conventions and auditing a site

How to name input types, layouts and layout areas so that the author's pickers stay usable and no area clashes with a getter; a quarterly audit for unused layouts, duplicate input types and orphaned areas; and what tags and categories on components actually organise.

Who this is for. Content modellers and lead developers responsible for a site that keeps growing; two hundred layouts and ninety-five input types is a normal end state. After this page you have naming rules to hand to the team and an audit to run each quarter.

What the names are for

Authors find layouts by name, and nothing else organises the lists they choose from:

  • The layout picker on a record lists the layouts for that kind of record (pages, blog posts and so on) that belong to the record's site or to no site, plus the record's current layout. It is one flat list, sorted alphabetically by name.
  • The component picker, used when an author adds a component to an area, shows the component layouts (layouts with no controller) that are not hidden and belong to the current site or to none. Each is a tile: the layout's thumbnail, or a generic icon, and its name. The area's supported layouts narrow the set, and the author can search by name.
  • Layout categories play no part in either picker. They appear on the layout's own form, on the screen that manages them and in the API, and nowhere an author chooses a layout.

So the name is the only thing that groups related layouts where authors browse them. The admin's side of this is on Thumbnails, categories and the author's picker.

Naming layouts

  • Lead with the family, then the variant, so that the alphabetical sort keeps siblings together: “Hero, split”, “Hero, full width”, “Card, person”, “Card, event”. “Split hero” and “Full-width hero” sort apart.
  • Name a layout for what the author gets, in the author's words, not after the template file or the design ticket.
  • Keep the template path parallel to the name, such as components/hero-split.html, so that a developer can go from one to the other.
  • Give every component layout a thumbnail: in the component picker the tile is the thumbnail and the name, nothing more.

Naming input types

An input type is chosen when a layout area is created, by whoever builds layouts, so its name serves them rather than authors. Name it for what it holds and how it is edited (“Button style”, “Content width”, “Heading level”), not for the first layout that used it. A select's name says which set of options it offers, because two selects with different options are two input types. Before creating one, look for an existing type with the same category, editor and options.

Naming layout areas

  • Use camelCase, the form the shorthand reads: heading, preHeading, componentStyle, printed as {$component->preHeading}. A flag named after its class, such as columns--reverse (Pattern: attributes to CSS classes), is the exception: it is only read with getAreaText(), so the shorthand does not need to reach it.
  • Use the same name for the same meaning on every layout. A heading is heading everywhere; shared templates, the attributes helper and the audit below all depend on it.
  • Name a select after the property it sets (componentWidth, textAlignment), and its option keys after the classes they produce.
  • Avoid the names in the next table.

Names a getter already takes

The shorthand calls the record's own getter when one exists, and the getter wins over an area of the same name. An area called url on a page is never reached by {$page->url}, which prints the page's URL. The area can still be read with getAreaHtml('url') or getAreaText('url'), but every template author has to know that. Each kind of record has its own getters; these are examples from two of them, not one list for every record:

RecordArea names its getters take
A pageid, name, url, slug, fullPath, position, created, modified, published, site, language, owner, parent, children, html, tags, categories, revisions, activeRevision, seoSettings, customUrl, externalId
A componentlayout. A component has no url getter, so url is free there.

Before naming an area anything short, check the record's methods in the Models reference.

Area names are effectively permanent

Content is linked to its layout area by the area's id, not its name, so renaming an area in the admin keeps every record's content: it is read under the new name from then on. What breaks is everything that still asks for the old name, and nothing warns you: no compiler or editor checks a template against the layout. In Smarty the shorthand raises Property intro does not exist; what the other reads and the API do with the old name is on Where content is stored, and what a change does to it. Treat a name that is in use as permanent, and when one must change, follow Renaming and retiring without losing content.

A quarterly audit

Run it every quarter and give it a named owner: someone who can hide layouts and knows whom to ask before anything is deleted. Write down what was found and what was changed, so that the next audit starts from it.

The platform has no report of which records use a layout, or of whether a component layout is still placed anywhere. Global components are the exception: the global component model counts its uses with getNumUsedInContent(), which counts every collection element that holds it, but a direct use in a component area only as present or absent. Everything else is built from two sides: the templates in the repository, and the content, through the admin's listings or the API.

Unused layouts

  1. Start from the admin's Layouts list: every layout, with its template path.
  2. For each page layout, list the records on it. A layout that no record uses and no one plans to use is a candidate.
  3. For each component layout, look for it in the content of the records that can hold it. The include count below shows only where templates include a component directly; a component an author placed is rendered through its layout, so a template the count never finds can still be in use.
  4. Hide the candidates. Do not delete them: deleting a layout runs no check for records that use it, and only users of the Developer type can do it. A hidden layout drops out of both pickers, while the records already on it keep it.
  5. Delete a hidden layout in a later quarter, if nothing has asked for it back.

Layouts whose template is missing

A layout names its template by path. If the file is gone, a page on that layout answers HTTP 500, and a component on it renders blank with HTTP 200. Check for this case specifically, since the page still loads. Compare each layout's template path with the files in the repository.

Shell
# every component template the templates refer to, most used first
grep -rhoE 'components/[a-z0-9-]+\.html' templates/ | sort | uniq -c | sort -rn

# which templates read an area named "heading"
grep -rEl 'getArea\w*\(.heading.\)|->heading\b|\.heading\b' templates/

Treat a match of the second command as a lead, not proof: it also matches ->heading on an unrelated object that happens to have a property of that name.

Duplicate input types

List the input types and sort them by category and editor. Two types with the same category, editor and options are duplicates; two selects whose options differ by one are usually one select that needs one more option. Choose the one to keep, switch each layout area that uses the other to it, and retire the other. Within the same category the stored values survive the switch; what is checked on the next save is on Where content is stored, and what a change does to it.

Orphaned areas

An orphaned area is a layout area that no template reads: authors fill it in and nothing appears. For each layout, run the second command for each of its area names. An area with no reader is either a template fault or an area to hide. An area that has stayed hidden for a full quarter with no reader is a candidate for deletion, by the steps on Renaming and retiring without losing content.

Tags and categories on components

Two settings in the Common module's component settings let authors filter components by tag and by category: Use tags for components (useTags) and its companion for categories (useCategories). Both are off by default. They act on one picker only: the one an author uses to reuse an existing global component. With them on, that picker filters by tags and by categories as well as by name, and each filter can match all or any of the chosen values.

They do nothing for the component picker, where an author chooses which kind of component to add; that one is organised by thumbnails and names alone. So for a library past thirty components:

  • name the component layouts by family and give each a thumbnail, as above, so that authors can find the kind of component;
  • tag and categorise the global components, and turn the two settings on, once there are enough global components that a name search no longer finds the right one to reuse.

A third setting in the same group, Show name / globals inputs for re-using components (showNameInputs), is on by default; it shows the inputs an author uses to name a component and make it reusable.

Go deeper

Was this page helpful?

Your answer goes to the docs team.