Acquia Developer (D10) study materials
Acquia Developer (D10) study resources

Acquia Developer (D10): Module and Theme Development

Acquia Developer (D10) · Work through your exam, one topic at a time.

All guide sections

Module and Theme Development

What to know

A custom module needs an .info.yml file with name, type: module, and core_version_requirement. Drupal 10 uses PSR-4 autoloading: src/ maps to the module namespace. Routing lives in *.routing.yml, services in *.services.yml, and hooks in a .module file or, in modern code, as attributes on OOP hook classes.

Hooks are the extension mechanism: hook_form_alter(), hook_entity_presave(), hook_theme(). Preprocess functions (template_preprocess_node(), mytheme_preprocess_page()) prepare variables before Twig renders. Twig templates use {{ variable }}, {% if %}, and filters; |t translates, |raw bypasses escaping (a security smell).

A theme needs .info.yml declaring base theme, regions, and libraries. Libraries (*.libraries.yml) declare CSS/JS with dependencies, and are attached via {{ attach_library() }} or render arrays. Render arrays are the currency of theming: #theme, #markup, #attributes, #cache. Twig auto-escapes; PHP render arrays do not.

Traps

  • .info.yml vs .info: only YAML is valid in modern Drupal.
  • Hook naming: MODULENAME_form_alter, not mymodule_form_alter for a different module's hook-use the module that owns the hook.
  • Template suggestion order: more specific suggestions win (node--article--teaser.html.twig beats node.html.twig).
  • Library attachment: forgetting dependencies (e.g., core/jquery) breaks JS silently.
  • Twig debug: enabling it shows suggestions but must be off in production.

Rule of thumb

If you need to change output, prefer preprocess + Twig override; if you need to change behavior, use a hook or event subscriber. Never edit core or contrib directly.

Worked example

To add a CSS class to article teasers: implement mytheme_preprocess_node() and, when $variables['node']->bundle() === 'article' and view mode is teaser, append to $variables['attributes']['class'].