Get the FREE Ultimate OpenClaw Setup Guide →

building-themes

npx machina-cli add skill MacareuxDigital/concretecms-skills/building-themes --openclaw
Files (1)
SKILL.md
7.2 KB

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 the system_errors element 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.
  • 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).

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_required and footer_required elements 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.
  • Use Area for editable regions.
  • Single Page Templates (view.php): Must include the system_errors element and echo $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 div element with $c->getPageWrapperClass(). Do not apply this class to the body element.

5. Manage Assets

  • Use registerAssets() in PageTheme to 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.php or use a CIF XML file to install the theme.

Guidelines

  • Namespacing: Always follow Concrete CMS PSR-4 naming conventions.
  • Reference: Use concrete/themes/atomik as 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.php for metadata/scripts and header.php for navigation) to keep individual files simple and maintainable.
  • Page Wrapper: Always use $c->getPageWrapperClass() on a wrapper div immediately inside the body tag, rather than on the body itself. 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 assets array in concrete/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.
  • Grid Framework:
    • The $pThemeGridFrameworkHandle property 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, and nine_sixty.
    • If your theme uses a different CSS framework (like Tailwind CSS) or a custom grid system, do not define $pThemeGridFrameworkHandle.
  • 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\ContainerArea to define editable regions within the container.
    • Registration: Define containers in the package's config/install.xml file using the <containers> tag.
    • Usage: Containers are added to areas in the CMS by users, providing structured, reusable layouts.

Source

git clone https://github.com/MacareuxDigital/concretecms-skills/blob/main/building-themes/SKILL.mdView on GitHub

Overview

Learn how to build professional Concrete CMS themes from scratch. It covers directory structure, core files, asset management, and modern features like containers and grid support, with a reference to the Atomik theme for best practices.

How This Skill Works

Work starts by placing themes in a package or application directory, then creating core files such as page_theme.php, default.php, and view.php plus modular elements like header and footer. Assets are registered through PageTheme, and grid framework or container features are configured in page_theme.php. Templates should leverage Area regions and the recommended header_required and system_errors usage for robust rendering.

When to Use It

  • Starting a new Concrete CMS theme from scratch
  • Modifying an existing theme to enable containers and grid support (v9+)
  • Packaging a theme for portability within a Concrete CMS project
  • Creating modular header/footer elements for reuse across pages
  • Optimizing asset loading and framework selection with getThemeSupportedFeatures and grid handles

Quick Start

  1. Step 1: Create the theme directory in packages/your_package_handle/themes/your_theme_handle or application/themes/your_theme_handle
  2. Step 2: Add core files: page_theme.php, default.php, view.php, and header/footer elements; organize elements (header_top.php, header.php, footer.php, footer_bottom.php)
  3. Step 3: Implement page_theme.php with namespace, getThemeName()/getThemeDescription(), grid framework handle if needed, and registerAssets to load core assets

Best Practices

  • Place themes under a package (packages/your_package_handle/themes/your_theme_handle) for portability, or use application/themes/your_theme_handle/
  • Create core files: page_theme.php, default.php, view.php, and shared elements/header.php & elements/footer.php; split elements for clarity (e.g., header_top.php)
  • Configure page_theme.php with a proper namespace, getThemeName(), getThemeDescription(), and getThemeSupportedFeatures() if using a JS library; only set grid framework handle when using a core framework like bootstrap5 or bootstrap4
  • Use Area blocks for editable regions and wrap main content in a div with $c->getPageWrapperClass(); do not apply this class to the body
  • Register assets with registerAssets() and prefer core assets (jquery, bootstrap, vue) to ensure compatibility

Example Use Cases

  • A package-scoped corporate theme at Packages/MyCompanyTheme with Bootstrap 5 grid and a custom header/footer set
  • A blog theme using default.php and view.php templates, including system_errors and echo $innerContent; assets loaded via registerAssets
  • A modular theme that splits header into header_top.php, header.php, and header_bottom.php for flexible composition
  • A no-JS theme that omits getThemeSupportedFeatures() to avoid asset conflicts
  • An Atomik-style reference implementation in concrete/themes/atomik used as a practical guide for modern theme development

Frequently Asked Questions

Add this skill to your agents
Sponsor this space

Reach thousands of developers