This is the documentation for concrete5 version 5.6 and earlier. View Current Documentation

Building a theme is a great way to get started developing for concrete5. If you want to share your work and have it sold (or distributed freely) in our Marketplace, you'll need to make sure it's coded in a way that meets our requirements. This is a discussion of common and sometimes-not-terribly obvious issues that arise when a concrete5 theme is being reviewed.

If you're interested in developing a theme for the marketplace, start here: Theme Submission Guidelines.

Inconsistent code indentation

Please make your code readable. It makes our lives easier and will in turn help get your theme approved sooner. What do we want? This page has some good examples of how to approach indenting HTML.

Slamming every line to the left is bad too, since it makes it difficult to follow the structure of your page, at-a-glance. Don't make code spaghetti!

$c in Global Areas

This one’s easy to overlook. The code to create a regular concrete5 area is very similar to the code that creates a Global Area. Here’s a regular area:

    $a = new Area('Header Image');

And here is a Global Area:

    $a = new GlobalArea('Header Nav');

When you create a regular, standard area in a page type or theme element, you’ll call the display method on a variable named $c. $c is the collections object for the current page.

Since Global Areas are actually references to named Stacks-- and these stacks don’t live in the current page (‘cause they’re Global)-- don't reference $c when you make a Global Area. While doing so might not cause any obvious errors or issues, it’s programmatically incorrect and should be avoided.

Unnecessary assets

Our rule of thumb: if it doesn’t serve a purpose, it shouldn’t be included in your theme.

Let’s say a free template uses a bit of jQuery. As you converted it into a concrete5 theme, you realized that concrete5 makes jQuery available for you already-- so you removed the original script reference in the template's header. But did you remove the jQuery source out of your theme’s scripts folder as well? You should!

While a few extra files here and there might not take up much storage space, it's always a good idea to remove clutter. Leaving in unused assets around could be confusing to anyone who wants to troubleshoot or modify your design later.

Over-usage of getStyleSheet()

Beginning theme developers will often use getStyleSheet() to reference each and every stylesheet in their theme. But that’s likely not necessary. Although getStyleSheet() is a handy way to pull in a stylesheet, this particular method also parses the stylesheet for customizable theme styles-- the options defined to allow end-users to change simple styles from Dashboard > Pages & Themes > Themes > Customize).

If the particular stylesheet you want to load doesn’t have customizable styles, there’s no reason to tell concrete5 to look for them. Use getThemePath() instead!

Here’s a good usage of getStyleSheet(). We’re loading typography.css, which has a bunch of text styles that have been set up for users to customize.

<link rel="stylesheet" media="screen" type="text/css" href="<?php  echo $this->getStyleSheet('typography.css')?>" />

And here’s an example of where you’d want to use getThemePath() instead. This stylesheet is simply a grid / framework resource, and there’s nothing that’s been made customizable inside.

<link rel="stylesheet" href="<?php  echo $this->getThemePath(); ?>/css/960_24_col.css" />

Note that the the code here is factored a little differently-- since we're simply getting the path to the active theme and printing it out, we'll need to add the path to the specific stylesheet at the end as well.

Bad font attribution & unauthorized fonts

Sure, the font you want to include can be downloaded freely from the web. That’s cool. But do you have the right to re-distribute it?

All too often the fine-print of your font’s license will specifically prohibit distribution without explicit permission, or inclusion in web templates and themes. If we determine that you don’t have the right to include a font, we’ll ask you to remove it before we’ll consider approving the theme.

Another hint: the easier you make it for us to find the font's license information, the quicker we'll be able to check that requirement off our list.

  • Include a copy of the font's license as a .txt file, in your theme's folder.


  • Link to the place where you got the font from.

If you find that your font files can't be included for distribution, you might consider fetching an alternate font from a service like Google Webfonts.

Too many areas

We know that you want to give users the ability to add blocks in every different possible design configuration. We know that you want to show off the fancy new grid you’ve selected to build with. But making many tens of areas in a single concrete5 page type isn’t a good idea.

Why? Because as soon as your page type is applied, concrete5 will create each and every area for this page, in the database. If your page type has, say 200 areas, that means concrete5 has to interact with each whenever it loads the page or enters / leaves edit mode. If your users add layouts to any of these areas, even more database interaction will happen.

While this might not be huge drain on performance on a small, simple demo site, that doesn’t guarantee that the theme will behave properly in a different environment, such as a large site or a budget hosting environment. In this sense, it's a good idea to "aim for the middle" and make something that the vast majority of marketplace users will be able to apply to a site with a minimum of hassles.

Code in t() functions

When working in concrete5 you’ll often find text strings wrapped in a t() function. This allows your text to be easily translated by a number of different translation tools. But you should try not to include HTML in these functions if possible. This example is not ideal:

echo t('Built with <a href="" alt="Free Content Management System" target="_blank">concrete5 - an open source CMS</a>')?>

Instead, include your HTML as additional arguments in t() and then refer to each in your original string as %s. This will add our link code back into the page source, in the right spot, and keep things a bit cleaner for translators:

echo t('Built with %sconcrete5 - an open source CMS%s','<a href="" alt="Free Content Management System" target="_blank">','</a>')?>


I hope this helps you get your themes in top shape and ready for submission to the Peer Review Board! If you haven't done so already, make sure to check out the Theme Submission Guidelines as well. Good luck!

Loading Conversation