For many years we’ve been looking for the right tools to build our themes. We’ve also been looking for an easy to work with layout builder. Nowadays, our primary means to get the job done are Tailwind CSS along with our homegrown Pluggable entity view builder module (PEVB in short). Before diving into the technical bits, let me first state why these two tools work so well for us.

Standardization in multiple projects: We have a few projects going on in different states at any given time. Some are in the building state, others in maintenance. All of our developers cycle through the various projects to help out, learn, and not get too bored with a single project. Doing that also makes sure that we constantly have incremental improvements in our way of working. If something works well in one project, a developer will likely carry it over to the next project. Our Drupal-Starter kit is where this standardization is happening. If it’s “Drupal-starter worthy,” it means that eventually it should hit all projects.

Reduction in cognitive load: “Where is this element coming from” is a sentence I’ve whispered to myself many times in frustration while inspecting a Drupal page. Is it a block? A view? Was some data in it preprocessed and changed just before converting to HTML? We want all our projects to be predictable. That is, even if you are unfamiliar with a project, you should be able to find what you are looking for based on other projects.

Optimization for rewrites: Here’s a typical scenario we have had for many years and hated. We need to change some layout or CSS on an existing site. The chance that we would be able to simply delete some of the existing CSS is slim. It’s more likely that new lines would be added, with higher and higher specificity, while at the same time, the chances of breaking other elements get bigger and bigger. BEM? SMACSS? I don’t want to have to be even more disciplined (we already are). No, I want to be half asleep and delete what can be removed and have no fear about it.

I’d summarize the above points with a more straightforward point: “Quickest to develop, and easiest to maintain.” I don’t want to paint our technique as the definitive - “everybody else is wrong” - way. I’ve seen the arguments against Tailwind, and that’s fine. Different people may have different goals. For us, a utility-first, functional CSS framework like Tailwind helps us achieve those goals, and PEVB ties it into Drupal’s layout system.

PEVB is not much more than a wrapper around EntityViewBuilder. When you enable the module – in a very Gizra-y way – nothing happens. It’s now up to you as a developer to write your first PEVB plugin. A plugin is per entity bundle, and inside it, you may override various view modes of that bundle. The gist is that once you override a view mode, you have total control of what you’d want to print. Have a look at the example module that comes with PEVB. Thanks to this piece of code, the module will override the Full view mode of the Article content type when you enable it.

That’s it. But with this simplicity, the significant benefit is that all the rendering is happening in a single place. There is no longer the need to jump between different files and UI screens to figure things out. If it’s in that single plugin, it’s rendered. If not - it’s not. And for consistency, we’re always returning renderable arrays:

<?php
class NodeArticle extends EntityViewBuilderPluginAbstract {

  public function buildFull(array $build, NodeInterface $entity): array {
    // Header.
    $build[] = ['#markup' => "This will be printed in the Article's full node view"];

    // Title.
    $build[] = [
      '#theme' => 'your_fancy_page_title',
      '#title' => $entity->label(),
    ];

    // Body field.
    $build[] = $this->buildProcessedText($entity);
  }
}

We rely on traits to generalize standard code. For example, to render a body field, we use this method. You will see that we don’t try to override any formatter but rather wrap the output with our custom theme. The reason we don’t rely on formatters is our approach to theming tasks and style guide.

As we’ve stated earlier, writing the theme is often time more challenging than writing the logic. So every element starts with a static version that we add into a Style guide. Go ahead and give our Drupal-Starter a try. Navigate to the local style guide page and watch all the existing elements. We wouldn’t have been able to do it with a formatter, as formatters are tightly coupled with data. On the other hand, our Twig files get their variables and don’t care where they come from.

Style guide page, part of Drupal-Starter kit.

The final piece that ties everything nicely together is wiring it into the Paragraphs module. We build our homepage and other “Landing pages” (e.g., About us, Contact, etc.) with a single content type and a few Paragraphs types. Content editors love it because it gives them enough flexibility to mix and match elements while keeping them from making mistakes. You know, structured content and all the jazz.

Landing page node view.
Landing page node edit, showing Paragraphs.
amitaibu's profile

Amitai Burstein

@amitaibu