Twig Best Practices in Drupal
Twig should make markup understandable, not hide application logic. The best templates are boring: their variables are prepared, their structure is semantic, and their reuse follows component boundaries.
Know the template hierarchy
Start with theme debug output to see candidate template names and suggestions. Override the narrowest template that represents the design decision; broad overrides create accidental coupling.
Prepare, then print
Use preprocess hooks to derive presentation variables and Twig to escape and arrange them. Avoid reaching into deeply nested entity internals from templates. Includes are useful for components; macros are best reserved for pure markup helpers.
Debug without weakening production
Enable Twig debug and disable caching only in local settings. Inspect available variables, confirm cache rebuilds, and remove debug configuration before deployment.
Working example
{% include '@circuitfolio/components/badge.html.twig' with {
label: difficulty,
modifier: difficulty|clean_class
} only %}Start with template suggestions
When markup needs to differ for one bundle, view mode, field, or page, first look for the narrowest template suggestion Drupal already exposes. Replacing a broad template such as every node or every field can solve the immediate design problem while creating unrelated regressions elsewhere.
Theme debug output is valuable because it shows both the active template and the suggestions Drupal considered. That turns template discovery into an observable process instead of a filename guessing exercise.
Preserve renderable values
Drupal often passes render arrays into Twig rather than plain strings. Printing the renderable value allows Drupal to keep its attached libraries and cache metadata. Reaching deeply into entity internals to extract a raw value may accidentally bypass formatting, access decisions, or cacheability that the field formatter already provides.
When a custom variable really is needed, prepare it deliberately in preprocess code and give it a name that describes the presentation concept.
Make component inputs explicit
Reusable includes become easier to maintain when they receive only the variables they require. Using only prevents an include from silently depending on the entire parent context. That makes the component easier to move, test, and reason about later.
The same principle applies to CSS. A component should have a recognizable class contract instead of depending on where it happens to be nested in one specific page template.
Key Takeaways
- Override the narrowest appropriate template.
- Prepare complex variables outside Twig.
- Use
onlywith includes to make dependencies visible.