Concrete CMS 9 · Updated 2026-09-03
A page template is a PHP file in your theme plus a database record telling Concrete the template exists. Miss the second half and your file sits there unused.
Create the file in your theme folder, named after the handle you want: landing.php for a handle of landing. A minimal template includes the theme's header and footer and declares its areas:
<?php
defined('C5_EXECUTE') or die('Access Denied.');
use Concrete\Core\Area\Area;
$view->inc('elements/header.php');
$a = new Area('Main');
$a->enableGridContainer();
$a->display($c);
$view->inc('elements/footer.php');
Areas are created the moment they are displayed on a page; there is nothing to register. Give them names that describe the slot, because editors see those names.
Add it under Pages & Themes → Page Templates, giving it the same handle as the filename. If the template is part of a package you are shipping, register it in the package's install() instead, so a fresh install gets it automatically:
use Concrete\Core\Page\Template as PageTemplate;
if (!PageTemplate::getByHandle('landing')) {
PageTemplate::add('landing', t('Landing'), 'landing.png', $pkg);
}
The third argument is an icon filename from the core's page-template icon set. Passing the package as the fourth argument ties the template's lifetime to the package, so uninstalling cleans up after itself.
Page types control which templates are offered. A page type set to allow all templates picks up the new one immediately; one with an explicit list needs the new template added to it. Editors then choose it from the page's Design panel or when adding a page.
Handles are shared across themes, and that is useful. If your custom template uses the same handle as one another theme provides, pages built on it keep rendering when you switch themes. Reusing the conventional handles (full, left_sidebar, right_sidebar, blank) is usually better than inventing new ones.