---
title: "Gutenberg"
menu:
  main:
    parent: "guides"
---
## Using Gutenberg with Timber

Timber works with Gutenberg out of the box. If you use `{{ post.content }}`, Timber will render all the Gutenberg blocks.

## ACF Blocks

### What are ACF Blocks?

ACF Blocks are an alternative way to create content blocks without advanced JavaScript knowledge. If you want to learn more about them, read the article on [advancedcustomfields.com](https://www.advancedcustomfields.com/blog/acf-5-8-introducing-acf-blocks-for-gutenberg/).

### How to use ACF Blocks with Timber

Before you can start using ACF Blocks, you must install the Advanced Custom Fields 5.8.0-beta version or later.

To create a content block, you first have to register it in **functions.php** or in a separate plugin:

```php
add_action( 'acf/init', 'my_acf_init' );

function my_acf_init() {
    // Bail out if function doesn’t exist.
    if ( ! function_exists( 'acf_register_block' ) ) {
        return;
    }

    // Register a new block.
    acf_register_block( array(
        'name'            => 'example_block',
        'title'           => __( 'Example Block', 'your-text-domain' ),
        'description'     => __( 'A custom example block.', 'your-text-domain' ),
        'render_callback' => 'my_acf_block_render_callback',
        'category'        => 'formatting',
        'icon'            => 'admin-comments',
        'keywords'        => array( 'example' ),
    ) );
}
```

Next, you you have to create your `render_callback()` function:

```php
/**
 *  This is the callback that displays the block.
 *
 * @param   array  $block      The block settings and attributes.
 * @param   string $content    The block content (emtpy string).
 * @param   bool   $is_preview True during AJAX preview.
 */
function my_acf_block_render_callback( $block, $content = '', $is_preview = false ) {
    $context = Timber::context();

    // Store block values.
    $context['block'] = $block;

    // Store field values.
    $context['fields'] = get_fields();

    // Store $is_preview value.
    $context['is_preview'] = $is_preview;

    // Render the block.
    Timber::render( 'block/example-block.twig', $context );
}
```

You create an extra array called `$context` with three values:
- **block** - with all data like block title, alignment etc
- **fields** - all custom fields - also all the fields created in **ACF**
- **is_preview** - returns true during AJAX preview

Finally, you can create the template **block/example-block.twig**:

```twig
{#
/**
 * Block Name: Example block
 *
 * This is the template that displays the example block.
 */
#}

{% if is_preview %}
    <p>I will only appear in the editor.</p>
{% endif %}

<div id="example-{{ block.id }}" class="wrapper">
    <h1>{{ fields.title }}</h1>
    <p>{{ fields.description }}</p>
</div>
<style type="text/css">
    #testimonial-{{ block.id }} {
        background: {{ fields.background_color }};
        color: {{ fields.text_color }};
    }
</style>
```

If you would like to use an external stylesheet both inside of the block editor and the frontend you should add:

```php
function my_acf_block_editor_style() {
    wp_enqueue_style(
        'example_block_css',
        get_template_directory_uri() . '/assets/example-block.css'
    );
}

add_action( 'enqueue_block_assets', 'my_acf_block_editor_style' );
```

For more details about enqueueing assets read the [Gutenberg Handbook](https://wordpress.org/gutenberg/handbook/blocks/applying-styles-with-stylesheets/#enqueueing-editor-only-block-assets).

### Using repeaters

```
{% for field in fields.repeater %}
    Title: {{ field.title }} <br/>
    Url: {{ field.url }}
{% endfor %}
```

### Using groups

```
Title: {{ fields.group.title }} <br/>
Url: {{ fields.group.url }}
```
