← All posts

Crafting Reusable Twig Components in FlyntWP: The Icon Example

Crafting Reusable Twig Components in FlyntWP: The Icon Example

I'm a developer who genuinely enjoys building things, but for years, I wrestled with the bloat and limitations of conventional page builders. They promised speed and flexibility, but often delivered sluggish sites, messy DOM structures, and a frustrating lack of control. That's why stumbling upon FlyntWP felt like finding an oasis in the desert. It’s a framework that brings back the joy of programmatic development to WordPress, offering a refreshing alternative that prioritizes performance, clean code, and developer sanity.

One of FlyntWP's core strengths, and a major reason our sites consistently hit flawless Core Web Vitals, is its modular Twig component architecture. Instead of monolithic blocks of HTML, we build our sites out of small, self-contained, and highly reusable Twig components. This isn't just about tidiness; it’s about efficiency, maintainability, and ultimately, delivering a blazing-fast user experience. When every piece of your UI is a component, you can update, reuse, and optimize it with surgical precision.

Let me walk you through a practical example of how this plays out, using a common element: an icon. Instead of hardcoding SVGs or relying on an icon font that might load an entire library for one icon, we create a dedicated `icon` component.

First, let's define our simple `icon.twig` component, located in `components/icon/icon.twig`:

<svg class="icon icon--{{ name }} {{ class }}" aria-hidden="true" width="{{ size }}" height="{{ size }}"> <use href="/assets/icons.svg#icon-{{ name }}"></use> </svg>

Notice how it takes `name`, `size`, and `class` as parameters. This component assumes you’ve got an SVG sprite `icons.svg` (which Vite handles beautifully, by the way, for lightning-fast build times during development and optimized production assets). The `name` parameter dynamically pulls the correct icon from that sprite. The `size` and `class` parameters give us flexibility for styling the icon when it's rendered.

Now, let's say we want to use this `icon` component within another component, perhaps a Call To Action block that features an icon next to its heading. Our `BlockCallToAction.twig` might look something like this:

<section class="block-call-to-action {{ fields.className }}"> <div class="container"> {% if fields.icon %} {% include 'components/icon/icon.twig' with { name: fields.icon, size: '24', class: 'block-call-to-action__icon' } %} {% endif %} <h2>{{ fields.title }}</h2> <p>{{ fields.content }}</p> <a href="{{ fields.link.url }}" class="button">{{ fields.link.title }}</a> </div> </section>

Here's where the magic of FlyntWP and ACF Pro really shines. The `fields.icon` variable isn't just some arbitrary string; it's dynamically pulled from an ACF field that the content editor sets in the WordPress admin. We'd have a simple text field in our ACF field group for the `BlockCallToAction` called `icon`, where the editor could type something like `arrow-right` or `check-mark`. This allows content editors to easily control which icon appears, without ever touching code.

This pattern isn't just for icons. Imagine a `button` component, a `card` component, or even a `heading` component. Each one is a small, encapsulated piece of UI that knows how to render itself based on the data you pass it. This approach leads to incredibly clean, semantic HTML output, which is the bedrock of excellent Core Web Vitals scores. No extraneous divs, no inline styles from a page builder, just exactly what the browser needs to render your content efficiently.

By leveraging modular Twig components with ACF Pro for data management and Vite for its incredible build speed, FlyntWP empowers us to build truly performant, scalable, and delightful WordPress experiences. It moves us away from the drag-and-drop sluggishness and back into a world where code is king, and performance is paramount. This specific technique of componentizing even the smallest UI elements is fundamental to unlocking FlyntWP's full potential.