The following guidelines have been written to provide optimal performance, scalability, maintainability, and flexibility within a CMS system.
This document uses the following conventions to express intent:
- SHALL: The statement that follows must always be followed.
- SHALL NOT: The statement that follows must never happen.
- SHOULD: If the statement that follows can happen, then it must happen.
- SHOULD NOT: If the statement that follows doesn't need to happen, then it must not happen.
- MAY: The statement that follows is not required, but can be considered an exemption to a previous statement.
Developer SHALL NOT use text-transform. Letter casing SHALL be determined by the content added in the CMS.
Developer SHALL use em-units for line-spacing and letter-spacing.
Developer SHALL use rem-units for font-size unless the design requires an elastic or otherwise formulaic sizing of fonts.
Developer SHALL NOT include fonts within the theme files.
Fonts MAY be pulled from a third-party API.
Fonts MAY be uploaded to the CMS via fields in the admin.
Fonts SHALL be presented as options in the CMS to select from.
Font families SHALL be declared as css variables, with values pulled from CMS options.
Developer SHOULD NOT use white-space for controlling text-wrapping except for output of code or block quotes.
Developer SHALL NOT use hardcoded colors in stylesheets. Colors SHALL be declared as css variables, with values set from CMS options.
Developer SHALL NOT restrict color options within the CMS. Color selections SHALL use a color picker which provides at least a 16 bit color spectrum to choose from.
Developer MAY provide swatches of specific colors in the CMS as a supplement to the color picker as a convenience for choosing consistent color schemes.
Images SHALL use upload fields in the CMS admin.
Images of any aspect-ratio SHOULD be accomodated.
Developer SHALL NOT use hardcoded images as part of a theme.
Developer MAY use hardcoded images to display a complex shape not otherwise easily achievable through css, that is a permanent affixment of the design, that does not hold semantic value, and is not capable of being an upload option in the CMS. This exception allows only for purely decorative features of a design, and should be avoided as often as possible, opting instead for an image upload in the CMS, or using CSS to achieve the desired decoration.
Developer SHALL use inline SVGs in the DOM, or base64 encoded SVG in CSS where a hardcoded image is required for complex shapes or masking.
Inline SVGs SHALL use css variables for colors if the SVG uses colors.
Colors used within an inline SVGs SHALL be be determined by selections made in the CMS.
Developer SHALL NOT use a global, common grid. Even when designs use a grid system, there are nearly always elements which are designed as exceptions to the rule and should not be coerced into it. Code to the design, not to a framework.
Developer MAY use a global formula/mixin for dynamically generating a grid per section. One section may have a 12 column grid, while the following section may have a 16 column grid, and the following section may require a 300px sidebar aside a 10 column, flexible-width grid. Should Developer use a global mixin or formula, it SHALL be capable of accommodating this level of complexity.
Developer SHALL build sections in such a way that they may be arranged in any order with other sections on the page. The sections SHALL be arrangeable by the client in the CMS, without detrimental rendering issues on the front-end of the site.
Developer SHOULD NOT use *top, *right, *bottom, *left CSS rules for positioning or defining the box model. Developer SHOULD use *-inline* and *-block* rules to maximize compatibility with different languages such as rtl. E.g. padding-inline-start: 1rem
is far more reliable for rtl layouts than padding-left: 1rem
.
Developer SHOULD NOT use a single, site-wide, global stylesheet. Each page or section of a page SHALL have its own stylesheet comprising styles used for the page or section specific elements.
Developer SHOULD dynamically generate or combine stylesheets on page load, per page, based on the composition of the page, as long as the generated or combined stylesheet takes advantage of caching mechanisms to avoid regeneration each page load until the page content has been changed.
Developer SHALL NOT use @import
rules in compiled css to include other compiled css files. This causes an additional render-blocking request that cannot be deferred by the browser. Instead, compiled css files SHALL be loaded via link
tags.
Developer SHALL use import
statements for sharing functionality in JavaScript as often as possible.
Developer MAY use require
to include third-party libraries that do not support import
only when absolutely required due to compatibility issues. However, developer SHOULD use dynamic import
statements where static import
statements are not possible.
Developer SHOULD NOT use a single, site-wide, global JavaScript file. Each page or section of a page SHALL have its own JavaScript file comprising functionality used for the page or section specific elements.
Developer MAY use additional JavaScript files globally for the express purpose of providing functionality common to all pages and sections, such as the artifacts produced when using WebPack's Code Splitting techniques.
Developer SHALL mark fields required in the CMS if the field is required for proper rendering.
Developer SHALL check for values of a field before rendering the field's associated HTML markup.
Developer SHALL style components to render correctly with any combination of missing or present values of optional fields.
Developer SHALL set reasonable defaults for fields where it makes sense to do so. Prime examples are for font, color, and layout selections.
Developer SHALL use Observers in place of Event Listeners whenever reasonable. As an example, an IntersectionObserver is significantly more performant than listening on the scroll event. Likewise, a MutationObserver is significantly more performant than polling for an element or object property to exist.
Developer SHALL use requestanimationframe
when using javascript to apply styling, add or remove an attribute or attribute value, add or remove an element, or otherwise mutate the DOM itself. This has a significant impact on site performance.
Developer SHOULD relegate non-critical computations to requestIdleCallback()
where possible. This can have a significant impact on performance.
Developer SHALL provide interfaces for PHP classes meant to be extended or replaced.
Fields that have the option of returning objects SHALL be set to return the full object. This maximizes future compatibility for {MINOR} and {PATCH} versions without requiring changes to the field format.
Where a section design shows the option for a single button or link, the section SHOULD be capable of multiple buttons or links.
Where a section design shows the option for a contentful image (an image who's purpose is to be displayed as part of surrounding content, and not merely decorative), the option for a gallery SHOULD be provided.
Where a section design shows the option for a contentful image, the option for video embeds SHOULD be provided.
Where a section design shows the option for an image gallery, the gallery SHOULD be capable of both images and video embeds.
A section's name SHALL be derived from its purpose, rather than the specific content displayed in the design. E.g. if a design shows a list of amenities, an appropriate name is "List", rather than "Amenities".
A theme SHOULD use features and functionality provided by the CMS over custom-built duplications of such features.
A theme SHOULD NOT provide functionality to the CMS that is better isolated and served through a plugin for the CMS.
A theme MAY provide an options page within the CMS for global content and configuration.
A theme SHALL NOT provide more than 1 options page for theme settings.
A theme SHOULD minimize its number of plugin dependencies.
A theme SHALL make known any plugin dependencies within the CMS, and SHALL NOT allow itself to be activated if such plugin dependencies are unavailable.
A theme MAY install and activate dependencies upon theme activation.
A theme SHALL NOT remove, deactivate, upgrade, nor otherwise alter plugins that already exist within the CMS at any time.
A theme SHALL NOT remove, overwrite, append or prepend to, nor otherwise alter any content or options that already exist within the CMS at the time of activation that are not explicitly defined by, and exclusively used for the theme.
Elements of the theme SHOULD NOT use features that require code be written in the CMS.
Devloper SHOULD prefer specific rather than global options. For instance, a Map section would be a better place for a marker icon field, rather than a settings page.
Develop MAY add options in a settings page that serve as reasonable defaults for a section. For instance, a marker icon field on the settings page could be provided that serves as a default marker if one is not set on a section within a page.
Developer SHALL use semantic versioning with the following format: {MAJOR}.{MINOR}.{PATCH}
Developer SHALL increase the {PATCH} version by 1 when implementing bug fixes, or changing the DOM output, styles, or javascript of existing code.
A {PATCH} version SHALL NOT make any changes to the CMS admin area.
Developer MAY make presentational changes to admin field configurations that do not affect data values in a {PATCH} version. Examples include changing how wide a textarea field is presented, or whether a checkbox is displayed as a simple form element or a toggle switch.
Developer SHALL set the {PATCH} to 0 (zero), and increase the {MINOR} version by 1 when adding new functionality to the CMS admin, including adding new fields and rendering their associated data to the front-end.
Developer SHALL set the {PATCH} to 0 (zero), and increase the {MINOR} version by 1 when adding new PHP interfaces.
A {MINOR} version SHALL NOT contain changes to any existing fields in the CMS admin area that determine how information is saved to the database or the format of the data output when the information is retrieved in the front-end.
Developer SHALL set the {MINOR} version to 0 (zero), the {PATCH} version to 0 (zero), and increase the {MAJOR} version by 1 when changing existing fields in the admin in such a way as to effect how their data is stored or the format returned when the field is retrieved.
Developer SHALL set the {MINOR} version to 0 (zero), the {PATCH} version to 0 (zero), and increase the {MAJOR} version by 1 when changing the signature of a method, removing a method, or adding a method to an interface.
Version components SHALL NOT have a leading zero.
Developer SHALL create proper database migration scripts for converting the values from prior versions to the new value types. Migrations SHALL run automatically when the theme is updated through the CMS.