Design DataTwig

Dynamic Data With Twig

Use Twig expressions inside a Composer widget's HTML panel to output post data, apply filters, write conditions, and access site-wide values.

Twig is the expression language Composer uses for dynamic data inside a Composer widget's HTML panel. Write {{ post.title }} anywhere in the HTML and Composer replaces it with the current post's title when the page renders. No PHP, no shortcodes, no custom fields plugin required for standard WordPress data.

This is a UiChemy-built engine that uses Twig's syntax, not the full Twig library. Everything on this page, output expressions, filters, {% if %}, {% for %}, works as described, but there's no template inheritance ({% extends %}), no {% include %}, and no macros.

Where to Write Twig

Open a Composer widget in Developer Mode (Style tab → Edit Code) and write Twig expressions directly in the HTML panel. Twig is processed server-side before the HTML reaches the browser.

<article>
  <h1>{{ post.title }}</h1>
  <p class="date">{{ post.date|date('F j, Y') }}</p>
  <div class="excerpt">{{ post.excerpt }}</div>
  <a href="{{ post.link }}">Read More</a>
</article>

Output Expressions: {{ … }}

Use double curly braces to output a value:

{{ post.title }}
{{ user.name }}
{{ site.name }}
{{ post.meta('price') }}

Values are HTML-escaped automatically. To output raw HTML (like post content that contains markup), use the raw filter: {{ post.content|raw }}.

The Seven Data Providers

The free version only resolves post.title, post.content, post.link / post.url / post.permalink, and post.thumbnail / post.featured_image, plus the full image chain (src, alt, width, height). All other post fields (post.excerpt, post.date, post.author, post.categories, post.meta(), etc.) and the entire site, user, term, and request providers require UiChemy Pro and return empty on Free.

post: Current Post (partial Free)

{{ post.title }}           {# Post title #}
{{ post.id }}              {# Post ID #}
{{ post.excerpt }}         {# Excerpt #}
{{ post.content|raw }}     {# Rendered content #}
{{ post.date }}            {# Published date (raw) #}
{{ post.link }}            {# Permalink #}
{{ post.slug }}            {# Post slug #}
{{ post.status }}          {# Post status #}
{{ post.comment_count }}   {# Number of comments #}
{{ post.meta('key') }}     {# Custom field value #}

{# Chained, author object #}
{{ post.author.name }}
{{ post.author.email }}
{{ post.author.avatar('96') }}

{# Chained, featured image #}
{{ post.thumbnail.src }}
{{ post.thumbnail.src('large') }}
{{ post.thumbnail.alt }}

{# Chained, first category #}
{{ post.categories.name }}

product: WooCommerce Product (extends post)

{{ product.price }}              {# Formatted price HTML (use |raw) #}
{{ product.regular_price }}
{{ product.sale_price }}
{{ product.is_on_sale }}         {# Boolean #}
{{ product.sku }}
{{ product.stock_status }}
{{ product.stock_quantity }}
{{ product.is_in_stock }}        {# Boolean #}
{{ product.add_to_cart_url }}
{{ product.average_rating }}
{{ product.review_count }}
{{ product.short_description|raw }}
{{ product.description|raw }}
{{ product.slug }}
{{ product.link }}
{{ product.thumbnail.src }}

user: Current Logged-in User (Pro)

{{ user.name }}          {# Display name #}
{{ user.id }}
{{ user.email }}         {# Admin context only #}
{{ user.bio|raw }}       {# Biography (HTML) #}
{{ user.url }}           {# Website URL #}
{{ user.link }}          {# Author archive URL #}
{{ user.avatar('64') }}  {# Avatar URL at given size in px #}
{{ user.meta('key') }}   {# User meta value #}

term: Current Term (Pro)

{{ term.name }}
{{ term.id }}
{{ term.slug }}
{{ term.description }}
{{ term.count }}         {# Number of posts #}
{{ term.link }}          {# Archive URL #}

image: Image Object. Not used directly, it's returned by chained expressions like post.thumbnail:

{{ post.thumbnail.src }}
{{ post.thumbnail.src('thumbnail') }}
{{ post.thumbnail.src('medium') }}
{{ post.thumbnail.src('large') }}
{{ post.thumbnail.src('full') }}
{{ post.thumbnail.alt }}
{{ post.thumbnail.width }}
{{ post.thumbnail.height }}
{{ post.thumbnail.caption }}

site: Site-Wide Data (Pro)

{{ site.name }}
{{ site.description }}   {# Tagline #}
{{ site.url }}
{{ site.language }}
{{ site.logo.src }}      {# Site logo image #}
{{ site.icon.src }}      {# Site icon (favicon) #}
{{ site.option('key') }} {# wp_options value #}

request: URL Parameters (Pro)

{{ request.get('tab') }}   {# ?tab=value from URL #}
{{ request.url }}          {# Current page URL #}
{{ request.referrer }}     {# HTTP referrer #}

Filters: Transforming Values

Apply a filter with |filtername. Chain multiple filters with |filter1|filter2.

String filters:

{{ post.title|upper }}                   {# ALL CAPS #}
{{ post.title|lower }}                   {# all lowercase #}
{{ post.title|capitalize }}              {# First letter capitalized #}
{{ post.title|title }}                   {# Title Case #}
{{ post.excerpt|trim }}                  {# Remove leading/trailing whitespace #}
{{ post.excerpt|truncate(120) }}         {# Max 120 characters, ends with … #}
{{ post.excerpt|truncate(120, '...') }}  {# Custom suffix #}
{{ post.excerpt|excerpt(25) }}           {# Max 25 words #}
{{ post.content|striptags }}             {# Remove HTML tags #}
{{ post.title|slug }}                    {# url-safe-slug #}
{{ post.title|replace('Old', 'New') }}   {# Find and replace #}
{{ post.title|split(' ') }}              {# Split into an array #}
{{ post.title|format('Post: %s') }}      {# sprintf-style formatting #}
{{ value|default('Fallback text') }}     {# Show fallback if empty #}
{{ post.content|wpautop|raw }}           {# Add paragraph tags (like WordPress) #}
{{ post.content|shortcodes|raw }}        {# Render WordPress shortcodes #}
{{ post.content|kses_post|raw }}         {# Sanitize to allowed post HTML #}
{{ post.content|raw }}                   {# Output raw HTML #}
{{ post.content|e }}                     {# HTML-escape explicitly #}
{{ value|esc_attr }}                     {# Escape for an HTML attribute #}
{{ url|esc_url }}                        {# Escape and validate a URL #}
{{ post.excerpt|nl2br|raw }}             {# Convert line breaks to <br> #}
{{ data|json_encode|raw }}               {# Encode a value as JSON #}

Number filters:

{{ product.regular_price|number_format(2) }}  {# 1,299.00 #}
{{ value|round(2) }}                           {# Round to 2 decimal places #}
{{ value|abs }}                                {# Absolute value #}
{{ product.price|currency|raw }}               {# WooCommerce price format #}

Date filters:

{{ post.date|date('F j, Y') }}      {# January 15, 2025 #}
{{ post.date|date('d/m/Y') }}       {# 15/01/2025 #}
{{ post.date|date('M Y') }}         {# Jan 2025 #}
{{ post.date|time_ago }}            {# "3 days ago" #}

Array filters (for multi-value fields like categories or gallery):

{{ post.categories|first }}            {# First item #}
{{ post.categories|last }}             {# Last item #}
{{ post.categories|length }}           {# Count of items #}
{{ post.categories|reverse }}          {# Reversed array #}
{{ post.categories|sort }}             {# Sorted array #}
{{ post.categories|keys }}             {# Array keys #}
{{ post.categories.name|join(', ') }}  {# "News, Updates, Reviews" #}
{{ post.categories|map(c => c.name) }} {# Transform each item #}
{{ post.categories|filter(c => c.count > 0) }} {# Keep matching items #}
{{ post.categories|find(c => c.slug == 'news') }} {# First match #}

map, filter, and find accept an arrow-function argument (item => item.field), a small non-standard extension for working with arrays of objects.

Conditions: {% if %}

Show content conditionally:

{% if post.thumbnail %}
  <img src="{{ post.thumbnail.src('large') }}" alt="{{ post.thumbnail.alt }}">
{% endif %}

{% if user.id %}
  <p>Welcome, {{ user.name }}!</p>
{% else %}
  <a href="/login">Log in</a>
{% endif %}

{% if product.is_on_sale %}
  <span class="badge">Sale</span>
{% endif %}

Structural Tags

Five <uichemy-*> tags render whole WordPress blocks. Place them directly in the HTML panel:

<header>
  <uichemy-site-logo></uichemy-site-logo>
  <nav><uichemy-nav-menu></uichemy-nav-menu></nav>
</header>

<main>
  <uichemy-post-content></uichemy-post-content>
  <uichemy-toc></uichemy-toc>
</main>
TagWhat it outputs
<uichemy-nav-menu>Active WordPress navigation menu
<uichemy-site-logo>Site logo linked to home
<uichemy-site-icon>Site icon linked to home
<uichemy-post-content>Current post content
<uichemy-toc>Table of contents from post headings

Use Cases

  • Formatting a value inline, dates, capitalization, or truncated excerpts, with a filter instead of a dynamic tag sub-option.
  • Showing or hiding content conditionally, for example, only rendering a "Sale" badge when a product is on sale.
  • Chaining across providers, drilling from a post to its author, or a product to a related term, in one expression.

Frequently Asked Questions