Jump to Navigation Jump to Main Content Jump to Footer
Home » Docs » Features » Twig templating support with Timber + Timber cache integration

Twig templating support with Timber + Timber cache integration

Chisel uses Timber to bridge WordPress data with Twig templating, creating clean, maintainable views. Twig keeps markup expressive and logic-light while Timber provides elegant object-oriented access to WordPress content.

The integration includes environment-aware caching that auto-reloads in development and compiles templates for production. Custom Timber classes extend posts, terms, and images with domain-specific methods, keeping templates declarative.

Global context automatically includes menus, sidebars, logo, and title data. Custom Twig functions handle responsive images, BEM classes, breadcrumbs, icons, and more—all registered via a clean, extensible architecture.

Bootstrapping and architecture

Core initialization

File: core/WP/Site.php

  • Site class extends Timber\Site and initializes Timber integration
  • Registers global context additions via add_to_context()
  • Configures class maps for custom Timber objects (posts, terms, images)
  • Adds custom Twig template locations via timber/locations filter

File: core/WP/Twig.php

  • Twig class extends Twig environment with custom functions, filters, and tests
  • Registers helper functions accessible in all Twig templates
  • Provides extension points via chisel_twig_register_functionschisel_twig_register_filterschisel_twig_register_tests actions

File: core/Timber/Cache.php

  • Cache class configures Timber’s caching behavior
  • Sets cache mode via timber/cache/mode filter (defaults to CACHE_NONE)
  • Controls Twig environment options: cacheauto_reloaddebug
  • Cache behavior adjusts automatically based on WP_DEBUG and environment type

File: core/Timber/Components.php

  • Static methods for retrieving reusable site components
  • Includes: get_menus()get_logo()get_sidebar()get_footer_sidebars()get_the_title()get_icon()
  • Components are cached internally (request cache) to avoid repeated computation

Global context

Every Timber render automatically includes these context variables (added in Site::add_to_context()):

  • logo → Responsive HTML for the custom logo from Components::get_logo()
  • menus → Array of registered navigation menus via Components::get_menus()
  • sidebar → Dynamic sidebar content based on context (blog, WooCommerce, or custom)
  • copyright → Copyright sidebar from Components::get_sidebar('copyright')
  • footer_sidebars → Footer columns with automatically calculated grid classes
  • the_title → Page/archive title with class (respects ACF page_title_display field)

Usage in templates

<header>
  {{ logo }}
  {{ get_nav_menu('primary') }}
</header>

<aside>
  {{ sidebar.content }}
</aside>
Twig

Custom Timber classes

Chisel provides custom Timber classes for posts, terms, and images with helpful methods that keep Twig templates clean.

File structure

Location: core/Timber/

  • ChiselPost.php → Base class for posts and pages
  • ChiselProduct.php → WooCommerce products (extends ChiselPost)
  • ChiselTerm.php → Base class for terms
  • ChiselProductCategory.php → WooCommerce product categories (extends ChiselTerm)
  • ChiselImage.php → Attachment images with responsive methods

Class mapping

Configured in: Site::post_classmap() and Site::term_classmap()

Post TypeMapped Class
postChiselPost
pageChiselPost
productChiselProduct
attachmentChiselImage
Any other CPTsChiselPost (default)
TaxonomyMapped Class
categoryChiselTerm
product_catChiselProductCategory
Any other custom taxonomiesChiselTerm (default)

ChiselPost methods

File: core/Timber/ChiselPost.php

  • get_thumbnail(string $size = 'medium', array $attrs = []) → Returns responsive <img> HTML with srcset
  • Automatically caches thumbnail HTML to prevent redundant calls
  • Falls back to empty string if no thumbnail exists

Usage in Twig:

{{ post.get_thumbnail('large') }}
{{ post.get_thumbnail('medium', { class: 'c-image' }) }}
Twig

ChiselProduct methods

File: core/Timber/ChiselProduct.php

  • Extends ChiselPost with WooCommerce-aware thumbnail handling
  • Provides placeholder image fallback for products without thumbnails
  • Respects WooCommerce image size filters

ChiselImage methods

File: core/Timber/ChiselImage.php

  • responsive(string $size, array $attrs = []) → Responsive HTML for attachment images

Usage in Twig:

{% set image = TimberImage(post.meta('gallery_image')) %}
{{ image.responsive('large', { class: 'c-gallery__image' }) }}
Twig

Extending with custom CPT classes

1. Create your custom class

File: custom/app/Timber/MoviePost.php

namespace Chisel\Timber;

use Timber\Post as TimberPost;

class MoviePost extends TimberPost {
    public function rating_badge(): string {
        $rating = $this->meta('rating');
        
        return $rating ? 'Rated: ' . esc_html($rating) : '';
    }
    
    public function release_year(): int {
        return (int) $this->meta('release_year') ?: 0;
    }
}
PHP

2. Register in class map

File: custom/app/WP/Site.php (override post_classmap())

use Chisel\Timber\MoviePost;

public function post_classmap(array $classmap): array {
    $classmap['movie'] = MoviePost::class;

    return $classmap;
}
PHP

3. Use in Twig

{% for movie in movies %}
  <div class="c-movie">
    <h3>{{ movie.title }}</h3>
    <span>{{ movie.rating_badge() }}</span>
    <span>{{ movie.release_year() }}</span>
  </div>
{% endfor %}
Twig

Extending existing core Timber classes

To add custom methods to Timber classes already registered in core/Timber/ (like ChiselPost, ChiselProduct, ChiselTerm), extend the core class instead of replacing it. This preserves core functionality while adding your custom methods.

File:

namespace Chisel\Timber;

use Chisel\Timber\ChiselPost as CoreChiselPost;

class ChiselPost extends CoreChiselPost {
    public function reading_time(): string {
        $word_count = str_word_count(strip_tags($this->content()));
        $minutes = ceil($word_count / 200);
        return $minutes . ' min read';
    }
    
    public function formatted_date(): string {
        return $this->date('F j, Y');
    }
}
PHP

File: custom/app/WP/Site.php (add to post_classmap())

public function post_classmap( array $classmap ): array {
		$custom_classmap = array(
			'post' => \Chisel\Timber\Custom\ChiselPost::class,
		);

		return array_merge( $classmap, $custom_classmap );
	}
PHP

Usage in Twig:

<article>
  <h1>{{ post.title }}</h1>
  <time>{{ post.formatted_date() }}</time>
  <span>{{ post.reading_time() }}</span>
  {{ post.get_thumbnail('large') }} {# Core method still available #}
</article>
Twig

By extending the core class, all existing methods like get_thumbnail() remain available while your custom methods are added.


Twig functions

All functions registered in core/WP/Twig.php via timber/twig filter.

Navigation and menus

  • get_nav_menu(string $name) → Retrieves menu from global context by name (e.g., 'primary')
<nav class="c-nav">
  {{ get_nav_menu('primary') }}
</nav>
Twig

Images

  • get_responsive_image(int $id, string $size = 'medium', array $attrs = []) → Responsive <img> HTML with srcset/sizes
{{ get_responsive_image(post.thumbnail_id, 'large', { class: 'c-hero__image' }) }}
Twig

BEM class generation

  • bem(string $name, mixed ...$modifiers) → Generates BEM classes with modifiers
  • post_classes(string $classes, string $prefix = 'c-post') → Transforms WordPress post classes to BEM format
<div class="{{ bem('c-card', 'featured', is_sticky ? 'sticky' : false) }}">
  {# Outputs: c-card c-card--featured c-card--sticky #}
</div>

<article class="{{ post_classes(post.class, 'c-article') }}">
Twig

Icons and components

  • get_icon(array $args) → Renders views/objects/icon.twig with caching
  • should_use_icons_module() → Checks if icons module is configured
{{ get_icon({ name: 'arrow-right', size: 'small' }) }}
Twig

Breadcrumbs

  • breadcrumbs() → Yoast SEO breadcrumbs (requires Yoast plugin)
{{ breadcrumbs() }}
Twig

Comments

  • comments_template() → WordPress comments list and form
{{ comments_template() }}
Twig

Slider helpers

  • slider_prepare_params(array $params) → Prepares slider data attributes from ACF block settings
{% set slider_attrs = slider_prepare_params(block.fields.slider_settings) %}
<div {{ slider_attrs.attrs|join(' ')|raw }}>
Twig

WooCommerce

  • timber_set_product(object $post) → Sets global $product for WooCommerce templates

Template locations and structure

Base templates

Location: views/

  • base.twig → Main layout template
  • index.twigpage.twigsingle.twigarchive.twig → Page templates
  • 404.twigsearch.twigauthor.twig → Special templates

Reusable components

Location: views/objects/views/components/views/partials/

  • objects/icon.twig → SVG icon renderer
  • components/ → Larger UI components
  • partials/ → Smaller template fragments

Block templates

Native blocks: src/blocks/{block-name}/{block-name}.twig

  • Automatically discovered via Blocks::twig_files_locations()
  • Compiled to build/blocks/{block-name}/{block-name}.twig

ACF blocks: src/blocks-acf/{block-name}/{block-name}.twig

  • Automatically discovered via AcfBlocks::twig_files_locations()
  • Compiled to build/blocks-acf/{block-name}/{block-name}.twig

Custom template override

Location: custom/views/

Custom Twig files here override core views. The Site::twig_files_locations() method prepends this location to the search path.


Caching and environment

Cache configuration

File: core/Timber/Cache.php

Cache mode (via timber/cache/mode filter):

  • Default: Loader::CACHE_NONE
  • Other options: CACHE_USE_DEFAULTCACHE_OBJECTCACHE_TRANSIENTCACHE_SITE_TRANSIENT

Twig environment options (via timber/twig/environment/options filter):

OptionDevelopmentProduction
cachefalse (filtered via chisel_environment_cache)true or false (if WP_DEBUG is false)
auto_reloadtruefalse
debugtruefalse

Environment detection

Controlled by ThemeHelpers::is_dev_env():

  • Returns true if WP_DEBUG is true or WP_ENVIRONMENT_TYPE is 'development'
  • Development: Twig auto-reloads templates on every change, debug mode enabled
  • Production: Twig caches compiled templates, no auto-reload

Cache expiry

Property: Cache::$cache_expiry (default: HOUR_IN_SECONDS)

Filter: chisel_cache_expiry

Used by CacheHelpers::expiry() when compiling components like icons and blocks.

Enable environment cache via filter:

add_filter('chisel_environment_cache', '__return_true');
PHP

Typical render flow

1. WordPress template file (e.g., page.php):

$context = Timber::context();
$context['post'] = Timber::get_post();
Timber::render('views/page.twig', $context);
PHP

2. Global context automatically includes:

  • logomenussidebarfooter_sidebarsthe_title
  • Added by Site::add_to_context()

3. Twig template (e.g., views/page.twig):

{% extends "base.twig" %}

{% block content %}
  <article class="{{ post_classes(post.class) }}">
    <h1>{{ post.title }}</h1>
    {{ post.get_thumbnail('large') }}
    <div class="c-content">
      {{ post.content }}
    </div>
  </article>
{% endblock %}
Twig

4. Blocks render their Twig via:

  • Native: BlocksHelpers::render_twig_file()
  • ACF: BlocksHelpers::acf_block_render()

Both discover and render {block-name}.twig from the appropriate build directory.


Extending Twig

Adding custom functions

File: custom/app/WP/Twig.php (using action hooks)

public function action_hooks(): void {
	add_action( 'chisel_twig_register_functions', array( $this, 'register_functions' ), 10, 2 );
	add_action( 'chisel_twig_register_filters', array( $this, 'register_filters' ), 10, 2 );
}

public function register_functions( \Twig\Environment $twig, \Chisel\WP\Twig $chisel_twig ): void {
	$twig->addFunction( new \Twig\Function( 'custom_fn', array( $this, 'custom_fn_callback' ) ) );
}

public function register_filters( \Twig\Environment $twig, \Chisel\WP\Twig $chisel_twig ): void {
	$twig->addFilter( new \Twig\Function( 'custom_filter', array( $this, 'custom_filter_callback' ) ) );
}
PHP

Benefits of Timber class maps

  • Domain model: Business logic lives in classes, not templates
  • Cleaner Twig: {{ product.get_thumbnail() }} instead of function calls
  • Type safety: IDE autocomplete and type hints for custom methods
  • Consistency: Every post type instance uses the same API
  • Testing: Easier to unit test class methods vs template logic
  • WooCommerce integration: Built-in placeholder and size handling for products

Best practices

  • Keep Twig templates declarative—move logic into Timber classes
  • Use custom/views/ to override core templates (avoids core modification)
  • Create custom Timber classes for CPTs with unique behavior
  • Leverage global context for site-wide data (menus, sidebars)
  • Use get_icon() for icons to benefit from automatic caching
  • Use bem() function for consistent BEM class generation
  • Place block-specific Twig templates alongside block code in src/blocks/ or src/blocks-acf/

Do you like Chisel?

Give it a star on GitHub!