Packaging a Theme


Let us know by posting here.

The Package Format

To distribute a Concrete theme, it's best to package it using the Concrete CMS Package format. This not only facilitates easy updates and deployment but is also required for submission to the Concrete marketplace. When packaging a theme, include various Concrete functionalities such as themes, blocks, and custom code. However, this guide focuses solely on packaging a theme.

To begin, create a directory in the packages folder with a unique name. For instance, if your theme is called "Urbanic," you might name the directory "theme_urbanic" to clearly indicate its content and purpose. This name becomes the package handle.

Place two essential files in this directory: an icon and a controller.php file. The icon, preferably square with rounded corners, represents the package. The controller.php is crucial for defining the package, its version, and includes installation and update routines.

Here’s an example structure for controller.php:

namespace Concrete\Package\ThemeUrbanic;
use Concrete\Core\Package\Package;
use Concrete\Core\Page\Theme\Theme;
defined('C5_EXECUTE') or die("Access Denied.");

class Controller extends Package {
    protected $pkgHandle = 'theme_urbanic';
    protected $appVersionRequired = '5.7.1';
    protected $pkgVersion = '1.0';

    public function getPackageDescription() {
        return t("Adds Urbanic Theme.");

    public function getPackageName() {
        return t("Urbanic");

    public function install() {
        $pkg = parent::install();
        Theme::add('urbanic', $pkg);

The namespace and class structure is critical. For example, the namespace should follow the pattern \Concrete\Package\YourCamelCasedPackageHandle. Additionally, the install method must correctly implement theme installation, with attention to passing the $pkg variable to the add method.

After setting up controller.php, move your theme from the application/themes/ directory to the package directory. Modify the namespace in your theme's page_theme.php file to align with the package structure. For example:

namespace Concrete\Package\ThemeUrbanic\Theme\Urbanic;

This ensures the theme is correctly recognized within the package context.

Once these steps are completed, your theme is packaged in a format suitable for the Concrete marketplace or sharing across Concrete sites.

Enabling Full Content Swap

Concrete CMS themes are evolving into standalone sites, featuring custom blocks, page templates, and attributes designed for specific configurations. To address compatibility issues with existing sites, we've introduced "Full Content Swap." This feature allows any Concrete package to replace an existing site's front-end content with theme-specific content upon admin consent, ensuring the theme appears as intended by its developers.

Package Your Theme

Ensure your theme is properly packaged. Details here.

Understand the Content Import Format

Learn the XML-based Content Import Format. It defines site structure and content for Concrete sites. For example:

  • Installing Dashboard Pages:

    <concrete5-cif version="1.0">
      <page name="Sitemap" path="/dashboard/sitemap" ...>
  • Activating Themes:

    <concrete5-cif version="1.0">
      <theme handle="elemental" activated="1"/>
  • Adding Page Templates:

    <concrete5-cif version="1.0">
      <pagetemplate handle="full" name="Full" ... />

Inspect concrete/config/install/packages/ for varying content.xml files.

Use Sample Content Generator

For version 8 or higher, use Migration Tool.

Generating Sample Content

Steps to use Sample Content Generator for creating content.xml files:

  1. Install both the theme package and the Sample Content Generator add-on.
  2. Start with a clean installation of the Blank starting point.
  3. Install and activate the Theme Package and Sample Content Generator add-on.
  4. Design your sample site: Page Types, Page Templates, content, and images.
  5. Use "Generate Install Data" in the Dashboard for export.
  6. Archive and download images. Store in "content_files" in your package.
  7. Generate content.xml and copy relevant content to a new file in your package.

Prepare Package

  • Add protected $pkgAllowsFullContentSwap = true; to package controller.php.
  • Create packages/your_package/elements/dashboard/install.php for user information.

Installation Steps

  1. Install on Blank Site: Delete application/config/database.php, clear databases, and reinstall Concrete with the blank starting point. Install your package and test.
  2. Install on Site with Full Content: Confirm the installation process on a site with the full Concrete Sample Install.

Testing and Adjustments

Expect initial failures and adjustments, especially while refining the content.xml file. Test installation on both blank and full-content sites for confirmation.