> For the complete documentation index, see [llms.txt](https://docs.acpt.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.acpt.io/dynamic-blocks/create-your-first-block.md).

# Create your first block

Step-by-step guide to creating a dynamic block with TWIG and ACPT meta fields

This guide walks you through building an **Event Card** block — a block that displays an event's title, date, location, and a "Featured" badge. It uses both block controls (set by the editor in the sidebar) and ACPT meta fields (stored on the post).

***

## Step 0 — Enable dynamic blocks

Go to **Settings → Content settings**, enable **Dynamic blocks**, and save.

Once enabled, a **Blocks** menu item appears in the ACPT admin sidebar.

***

## Creating a block

Navigate to **Blocks** and click **Create Block**. A 5-step wizard opens.

<figure><img src="https://3235524095-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fiyf0tSKPgXiyoQ3zV3I6%2Fuploads%2Fgit-blob-7eda0c16e107697f8868a527cb8d2ca1fd2a09ee%2FCreate-new-block-%E2%80%B9-ACPT-test-%E2%80%94-WordPress-05-02-2025_04_30_PM.png?alt=media" alt=""><figcaption></figcaption></figure>

***

## Step 1 — General

Set the block's identity:

| Field          | Description                                                                                                     |
| -------------- | --------------------------------------------------------------------------------------------------------------- |
| **Name**       | A unique slug in lowercase, e.g. `event-card`. This becomes the block identifier `acpt/event-card`.             |
| **Title**      | Human-readable label shown in the block inserter, e.g. `Event Card`.                                            |
| **Icon**       | A [Dashicons](https://developer.wordpress.org/resource/dashicons/) slug (e.g. `calendar-alt`) or an SVG string. |
| **Keywords**   | Words editors can type to find the block, e.g. `event`, `date`, `card`.                                         |
| **Post types** | Restrict the block to specific post types. If left empty it is available everywhere.                            |

> **Tip:** Block names are slugified automatically. Spaces become dashes; the final identifier is always prefixed with `acpt/`.

***

## Step 2 — Supports

Declare which built-in Gutenberg features the block supports. Enabling a support adds the corresponding control to the block toolbar or inspector.

| Support      | What it adds                                        |
| ------------ | --------------------------------------------------- |
| `align`      | Alignment toolbar (left, center, right, wide, full) |
| `typography` | Font size, line height, font family pickers         |
| `color`      | Text and background color pickers                   |
| `spacing`    | Padding and margin controls                         |
| `anchor`     | HTML anchor field for in-page linking               |

See the [Block Supports reference](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/) for the full list.

***

## Step 3 — Controls

Controls are custom inputs that appear in the **block inspector sidebar** when an editor selects the block. Their values are passed directly to your TWIG template as variables.

For the Event Card example, add:

| Control name  | Type   | Purpose                           |
| ------------- | ------ | --------------------------------- |
| `show_badge`  | Toggle | Show or hide the "Featured" badge |
| `badge_label` | Text   | The badge text, e.g. `Featured`   |

> **Naming rule:** Control names are lowercased and spaces are replaced with underscores. Dashes are also converted to underscores. A control named `Badge Label` → `{{ badge_label }}` in TWIG.

See [Block controls](/dynamic-blocks/block-controls.md) for the full reference of all 11 control types.

***

## Step 4 — Callback

This is your TWIG template — the HTML that gets rendered on the page.

The following variables are always available:

* **Global site variables** — `current_year`, `site_name`, `site_url`, `site_description`, `site_logo`
* **Block control values** — one variable per control, named after the control (e.g. `{{ show_badge }}`)
* **ACPT meta fields** — `acpt_{box_name}_{field_name}` for every field on the current post

Assuming the post has a meta box called `event_details` with fields `date`, `location`, and `description`, the Event Card callback looks like this:

```twig
<div class="event-card">

    {% if show_badge and badge_label %}
        <span class="event-card__badge">{{ badge_label }}</span>
    {% endif %}

    <div class="event-card__body">
        <h2 class="event-card__title">{{ get_the_title()|raw }}</h2>

        {% if acpt_event_details_date %}
            <p class="event-card__date">
                <strong>Date:</strong> {{ acpt_event_details_date }}
            </p>
        {% endif %}

        {% if acpt_event_details_location %}
            <p class="event-card__location">
                <strong>Location:</strong> {{ acpt_event_details_location }}
            </p>
        {% endif %}

        {% if acpt_event_details_description %}
            <div class="event-card__description">
                {{ acpt_event_details_description|raw }}
            </div>
        {% endif %}

        <a class="event-card__link" href="{{ get_permalink() }}">View event →</a>
    </div>

</div>
```

> **Important:** Always use the `|raw` filter when outputting HTML content (rich text fields, shortcodes, etc.) to prevent Twig from escaping the markup.

See [TWIG reference](/dynamic-blocks/twig-reference.md) for a complete list of available variables, functions, and filters.

***

## Step 5 — Style

Write scoped CSS for your block. Styles are injected automatically and scoped to a wrapper element, so there is no risk of leaking into other blocks.

Example CSS for the Event Card:

```css
.event-card {
    border: 1px solid #e0e0e0;
    border-radius: 8px;
    padding: 24px;
    font-family: inherit;
}

.event-card__badge {
    display: inline-block;
    background: #ff6b35;
    color: #fff;
    font-size: 12px;
    font-weight: 600;
    padding: 2px 10px;
    border-radius: 20px;
    margin-bottom: 12px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.event-card__title {
    margin: 0 0 12px;
    font-size: 22px;
}

.event-card__date,
.event-card__location {
    margin: 4px 0;
    color: #555;
    font-size: 14px;
}

.event-card__description {
    margin-top: 12px;
    line-height: 1.6;
}

.event-card__link {
    display: inline-block;
    margin-top: 16px;
    color: #0073aa;
    text-decoration: none;
    font-weight: 600;
}
```

***

## What's next

* [TWIG reference](/dynamic-blocks/twig-reference.md) — full list of variables, WordPress functions, and filters
* [Block controls](/dynamic-blocks/block-controls.md) — all 11 control types explained
* [Examples](/dynamic-blocks/examples.md) — more complete block examples
