Underscorefunk Design

Design, Illustration, Interaction, and Artistic Direction

Action driven WordPress themes without templates

One of the things that drives me a bit nuts with WordPress is having all of the template files living under the theme root. I think the true power of WordPress can be found in approaching it as an application platform. If we want to fully commit to this approach we’ll need to think about each request as a ‘request’ and not a ‘template’.

Let’s put conditional display logic as a control before loading partials/output instead of needing to filter template_include or anything more complex or opaque.

There are some really major benefits in doing this:

  • It’s pretty easy to get major components (or any component for that matter) of the site as an AJAX response because all output is created via actions that call get_template_part. You can capture buffers with ob_start() and ob_get_clean()
  • Conditional statements now happen before ‘get_template_part’ which creates a really nice separation of concerns. We no longer care about if something should display when we’re coding output.
  • We get better profiling because we can add time stamps before and after specific actions to measure the efficiency of output.
  • We can capture buffers and cache the output of the template action.

Some caveats:

  • You’ll still need to have a header.php and footer.php in the theme’s root so that other plugin’s custom templates remain compliant with your theme. They may have templates of their own that do things the traditional way, calling get_header(); and get_footer();

I’ve written about loading template parts with actions, but I haven’t touched on how to free yourself from WordPress’ default templates. We’re going to use the same engine room approach but with a few tweaks.

You’ll notice a few things that I do here to keep everything straight:

  • Prefix actions that are called from the theme using ‘theme_’. This makes it much easier to integrate other plugins (i.e. a plugin can hook theme_singular_header, etc). Plugin actions would be prefixed with a plugin prefix like ‘my_awesome_plugin_’ because there are multiple plugins. There is only one theme so I opt to go with something generic.
  • Actions are suffixed with their object and/or context. This makes it easy to see which level I’m working on; am I performing an action for the whole site or for a specific part of the site.

This might seem a little overwhelming but it will make sense if you keep in mind that we’re just repeating this process:

call an action*hook the action with a callback function that loads a template part→have partial generate output that either calls an action (repeating the loop)* which we’ll call container components, or generate output, which we’ll call content component.

Your theme file structure

Your theme will look something like this. I am including this early to give you a roadmap of where we’re going. This list of files isn’t exhaustive and intended to help you visualize your site’s structure with this new approach.

You’ll have additional folders in there and sub folders for ‘partials’ and ‘structure’ that contain actions and their corresponding output partials for other components.

Main Template (/index.php)

Here’s the file that will handle all of our requests.

Site Header (content component example)

/header.php – Header action call. This file is loaded by get_header();

/includes/structure/hooks.php – Header action hook

/includes/structure/site/header.php – Header action callback

/partials/site/header.php – Header output (the header is a content component)

Site Body (special case – container component example)

/body.php – Site body action call. The site body is one of the few cases where theme output might live outside of a partial. The reason we’re not using do_action( ‘theme_site_body’ ) in index.php is because its partial would need to call do_action( ‘theme_site_body’ ), creating a loop of actions calling themselves.

Singular (container component example)

Here’s our first true example of replacing a WordPress template with our new approach.

/includes/structure/hooks.php – Singular action hook

/includes/structure/singular/singular.php – Singular action callback

/partials/singular/singular.php – Singular output

Engine Room (/includes/structure/_hooks.php)

Here’s a better view of the structure hooks.

To summarize, here’s the pattern


Leave a Reply