@me/changelog: Drupal (Front End)

As a process to get a Drupal certification that is being pushed by work in a very rushed fashion (we're talking < 2 week prep on top of client deadlines). I'd probably be fine taking the test, but re-reviewing some concepts just in case. The following text emojis (see also: kaomoji) sum up some of my feelings on it:

(¬_¬) "( – ⌓ – ) (ᵕ—ᴗ—) (¬`‸´¬) ∘ ∘ ∘ ( °ヮ° ) ?

I'm just... tired yall.


Preprocess Functions Scraps

mytheme.themephp
1function mytheme_preprocess_node(&$variables) {
2$node = $variables['node'];
3$variables['my_custom_var'] = $node->get('field_summary')->value;
4}

Syntax

mytheme_preprocess_HOOK(&$variables)

$variables contain everything available in the template

Setting a custom variable

$variables['my_var'] = 'some value';

Accessing current node

$variables['node']

Accessing field values

$variables['node']->get('field_name')->value

Wrapper element attributes object

$variables['attributes']

Common use

Adding body classes, passing config values to templates, transforming data before render

Compare

hook_preprocess (all templates)

hook_preprocess_HOOK (specific template)

Drupal Behaviors

custom.jsjavascript
1// Drupal behavior pattern
2Drupal.behaviors.myBehavior = {
3	attach(context, settings) {
4		once('my-behavior', '.my-selector', context).forEach((el) => {
5		// code
6		});
7	}
8};

Review Concepts

Attach and detach methods

Why behaviors exist: re-fire on AJAX-loaded content, unlike $(document).ready()

context parameter: the DOM element being processed (not always document)

settings parameter: values passed from PHP via drupalSettings

once() utility to prevent duplicate behavior attachment

jQuery once vs native Drupal once (changed in Drupal 9.2+?)

Declaring JS in mytheme.libraries.yml

dependencies: declaring core/drupal , core/once , core/jquery

minified: true flag

header: true to load in <head> (usually avoid)

Passing PHP data to JS via #attached['drupalSettings']

JS aggregation in production

Views

Review Concepts

Display types: Page, Block, Feed, Attachment, REST Export

Contextual filters: receive argument from URL or a default value

"Provide default value" options: raw value, node ID, taxonomy term, PHP code

Validation options and "Action to take if filter value does not validate"

Relationships must be added before you can use related fields as contextual filters

Relationships: joins between entity types (e.g. node → taxonomy term → other content referencing that term)

Exposed filters vs contextual filters: know the difference

Views caching: time-based vs tag-based

Rendering a view programmatically: views_embed_view('view_name', 'display_id')

Sub-theme from a Base Theme

Review Concepts

base theme key in mytheme.info.yml

Inheritance: sub-theme inherits templates, libraries, and regions from base theme

Overriding: copy template from base theme into sub-theme to override

libraries-extend to add to a base theme library without replacing it

Common base themes: Drupal 11+: Gin Admin (based on Claro)

Starterkit workflow: php core/scripts/drupal generate-theme command

Layout Builder

Review Concepts

Core module (enable via Extend)

Two modes: layouts for content types (templated) vs individual overrides per node

Sections: a row with a chosen layout (one column, two column, etc.)

Blocks are placed inside sections

Layout Builder vs Panels vs Display Suite — know Layout Builder is the current core approach

Inline blocks: only exist within the Layout Builder context

Reusable blocks: shared across Layout Builder layouts

Security

Review Concepts

Text formats and risk of "Full HTML" given to wrong roles

Input filtering: which tags are allowed per format

File upload security: allowed extensions, file size limits

Role permissions — principle of least privilege

administer permissions as elevated risk

CSRF protection in forms (built into Form API)

Security advisories and the importance of keeping core/modules updated

Auto-escaping in Twig: output is escaped by default (feature, not a bug)

|raw filter bypasses escaping (dangerous if applied to user input)

{{ content.field_name }} is safe

{{ node.field_name.value|raw }} is risky

Xss::filter() and Html::escape() in preprocess functions

Never trust $_GET, $_POST, or route parameters without sanitization in .theme files

CSS injection via user-controlled class names (|clean_class filter)

Performance

Review Concepts

CSS/JS aggregation (Admin → Configuration → Performance)

Page caching and dynamic page cache modules

Cache tags, contexts, and max-age — the three axes of Drupal caching

Views caching settings (time vs tag-based)

Image optimization: image styles, lazy loading

CDN integration at the config level

Unnecessary library loading — attaching libraries globally vs only where needed

Render caching: #cache properties on render arrays

Avoiding uncached output in Twig ( {{ 'now'|date }} style antipatterns)

Image dimension attributes to prevent layout shift (CLS)

Deferring non-critical JS (preprocess: false pitfalls)

Heavy preprocess functions that run expensive queries on every page load