Building themes
Agent Skills for Concrete CMS
npx -y skills add MacareuxDigital/concretecms-skills --skill building-themesAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 9 stars9 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
This skill provides guidance and standard workflows for developing custom themes for Concrete CMS, including directory structure, page templates, asset management, and v9+ features like containers. Use this when creating or modifying Concrete CMS themes.
SKILL.md
7.2 KB, as published. Nobody here has run it
Building Themes
Overview
This skill enables the development of professional, feature-rich themes for Concrete CMS. It covers the essential components like page_theme.php, page templates, asset registration, and advanced features such as grid support and containers.
For the most up-to-date best practices and implementation examples, refer to the concrete/themes/atomik directory in the core. It serves as the primary reference for modern theme development in Concrete CMS.
Workflow
1. Setup Theme Directory
Themes should be placed within a package for better portability. Otherwise, they can be stored in the application directory.
- Path:
packages/your_package_handle/themes/your_theme_handle/ - Path:
application/themes/your_theme_handle/
2. Create Core Files
Every theme requires at least:
page_theme.php: The main configuration class for the theme.default.php: The default page template.view.php: Required for single pages. Should include thesystem_errorselement and$innerContent.elements/header.php&elements/footer.php: Shared header and footer.- Recommended: Sub-divide elements for simplicity (e.g.,
elements/header_top.php,elements/header.php,elements/footer.php,elements/footer_bottom.php).
3. Configure page_theme.php
- Define namespace:
Concrete\Package\YourPackageHandle\Theme\YourThemeHandle - Required Methods:
getThemeName(): Return the localized name of the theme.getThemeDescription(): Return the localized description of the theme.
- Implement
getThemeSupportedFeatures()to optimize asset loading.- JS Library Themes: If the theme includes a full-featured JavaScript library (e.g., Bootstrap 5 JS, jQuery), list all supported features (e.g.,
FeatureConstants::NAVIGATION,FeatureConstants::FORMS) to avoid conflicts with Concrete's internal asset loading. - No-JS Themes: If the theme does not include any JavaScript, it is recommended not to implement this method.
- JS Library Themes: If the theme includes a full-featured JavaScript library (e.g., Bootstrap 5 JS, jQuery), list all supported features (e.g.,
- Configure grid support via
$pThemeGridFrameworkHandle.- Core Frameworks: If using a supported framework (e.g.,
bootstrap5,bootstrap4), set this property to the corresponding handle. - Custom Frameworks: If the theme uses a custom or unsupported CSS framework (e.g., Tailwind, Bulma), do not set this property.
- Supported Handles: Find available frameworks in
concrete/src/Page/Theme/GridFramework/Type(e.g.,bootstrap5,foundation,nine_sixty).
- Core Frameworks: If using a supported framework (e.g.,
4. Implement Templates
- Use
$view->inc('elements/header.php')to include shared elements. For more modularity, use multiple includes like$view->inc('elements/header_top.php')and$view->inc('elements/header.php'). - Ensure
header_requiredandfooter_requiredelements are present.- Note on
header_required: It is recommended to pass metadata variables to this element. See the header_required snippet for the recommended implementation.
- Note on
- Use
Areafor editable regions. - Single Page Templates (
view.php): Must include thesystem_errorselement andecho $innerContent;to display system messages and single page content. See the system_errors snippet for the recommended implementation. - Wrap the main theme content in a
divelement with$c->getPageWrapperClass(). Do not apply this class to thebodyelement.
5. Manage Assets
- Use
registerAssets()inPageThemeto require core assets or provide theme-specific ones. - Prefer Core Assets: Always require core assets (e.g.,
jquery,bootstrap,vue) even if the theme directory contains the same libraries. This avoids conflicts and ensures compatibility with Concrete CMS's internal logic. - Minimize redundant CSS/JS by declaring what the theme provides.
6. Register Theme in Package
- Update the package
controller.phpor use a CIF XML file to install the theme.
Guidelines
- Namespacing: Always follow Concrete CMS PSR-4 naming conventions.
- Reference: Use
concrete/themes/atomikas the gold standard for implementation details. Other bundled themes may be legacy or for internal use. - Security: Include
defined('C5_EXECUTE') or die("Access Denied.");at the top of every PHP file. - Localization: Use
t()for all user-facing strings. - Modular Elements: For complex themes, it is recommended to split header and footer elements (e.g.,
header_top.phpfor metadata/scripts andheader.phpfor navigation) to keep individual files simple and maintainable. - Page Wrapper: Always use
$c->getPageWrapperClass()on a wrapperdivimmediately inside thebodytag, rather than on thebodyitself. This ensures that Concrete CMS's UI and dialogs work correctly within the theme's layout. - Asset Management:
- Core Libraries: Always prefer core assets over bundling your own for common libraries like jQuery, Bootstrap, moment.js, vue.js, and FullCalendar.
- Check Bundled Assets: To see which libraries are bundled in the core, check the
assetsarray inconcrete/config/app.php. - Conflict Prevention: Using core assets prevents multiple versions of the same library from being loaded, which can cause significant JavaScript errors.
- Theme Features:
- Use
getThemeSupportedFeatures()to declare what your theme provides. This prevents Concrete CMS from loading redundant or conflicting core assets. - If your theme is a "fully featured" theme with its own JS bundle, you should return an array containing all relevant
FeatureConstants. - If your theme is simple/static and has no JavaScript, omitting this method allows Concrete CMS to handle asset injection more predictably.
- Use
- Grid Framework:
- The
$pThemeGridFrameworkHandleproperty enables the built-in Layout system to use your theme's grid classes. - Only use this if your theme is compatible with one of the core grid frameworks found in
concrete/src/Page/Theme/GridFramework/Type. - Common handles include
bootstrap5,bootstrap4,bootstrap3,foundation, andnine_sixty. - If your theme uses a different CSS framework (like Tailwind CSS) or a custom grid system, do not define
$pThemeGridFrameworkHandle.
- The
- Modern Features: Favor Containers over hardcoded areas for flexible layouts in Concrete CMS v9+.
- Containers:
- Naming: Always ask the user for clarification before naming a container if the name is not explicitly provided.
- Element Path:
themes/your_theme_handle/elements/containers/your_container_handle.php - Implementation: Use
Concrete\Core\Area\ContainerAreato define editable regions within the container. - Registration: Define containers in the package's
config/install.xmlfile using the<containers>tag. - Usage: Containers are added to areas in the CMS by users, providing structured, reusable layouts.