Prior to Drupal 10.2 most plugin implementations required the use of annotations alongside a PHP class. Now Drupal supports and recommends the use of PHP attributes instead. During the transition, most developers will still need to know how to recognize and implement annotation-based plugins.
In this tutorial we'll:
- Provide a recipe for implementing annotation-based plugins.
- Demonstrate how to figure out where the code and metadata should live for annotation-based plugins.
By the end of this tutorial you should have a recipe for getting started with implementing annotation-based plugins, and a better understanding of how to figure out the details required to implement a given plugin type.
Many of Drupal's APIs that look like a bunch of configuration in a YAML file (migrations, menu links, etc.) are actually plugins in disguise. The YAML from these files is used as arguments to a generic PHP plugin class which then behaves differently depending on the provided values. As a developer, you probably don't need to know that menu links are plugins, but it can be helpful when debugging or just trying to get a better understanding of the big picture.
In this tutorial, we'll:
- Learn about how YAML-based plugins work
- Discuss how to find the implementation details for YAML-based plugins
- Walk through an example of implementing a YAML-based plugin
By the end of this tutorial, you should be able to recognize a YAML-based plugin definition, and author your own.
Upgrade to Drupal 11
FreeThere’s no one-size-fits-all path to upgrade from Drupal 10 to Drupal 11, but there is a set of common tasks that everyone will need to complete.
In this tutorial we’ll:
- Explain the differences between Drupal 10 and Drupal 11 that affect the upgrade path.
- Walk through the high-level steps required to upgrade from Drupal 10 to Drupal 11.
- Provide resources to help you create an upgrade checklist and start checking items off the list.
By the end of this tutorial you should be able to:
- Explain the major differences between Drupal 10 and 11.
- Audit your existing Drupal 10 projects for Drupal 11 readiness, and estimate the level of effort involved.
- Start the process of upgrading your site from Drupal 10 to Drupal 11.
In this tutorial, you’ll create and render a simple single directory component (SDC) in Drupal. You’ll set up the required files, call the component from a template, and confirm that Drupal renders it with its styles automatically attached.
By following along, you will:
- Scaffold the files for a basic card component.
- Reference the component in a node template.
- See how Drupal renders the component’s HTML and CSS together.
When you’re done, you’ll have a complete working example of a Drupal single directory component.
The component YAML file, with the suffix .component.yml, is the heart of every Drupal single directory component (SDC). This file describes how consumers can pass data (props) and nest content (slots) into the component. Similar to a PHP interface, the schema defined in a .component.yml file acts as a contract that tells consumers (both developers and low-code tools) what data a component accepts and what shape it expects.
In this tutorial, you’ll learn what each key in a component's YAML file does. You’ll see how the file names the component, describes its API, and helps low-code tools validate and expose your component. Then we’ll create a new card component with a card.component.yml file.
By following along, you will:
- Reinforce your understanding of where a Drupal component's YAML file lives and why it matters.
- Break down each top-level key—
$schema,name,description,props, andslots. - Learn more about what you can put into a .component.yml file.
By the end of this tutorial, you’ll have a discoverable card.component.yml file for a new card SDC and a mental model for how Drupal uses it.
Learn how to embed a Drupal single directory component (SDC) in a Twig template like node.html.twig. This tutorial explains how to pass props and slots to the component, how to determine the correct namespace and name, and how to choose between Twig’s {% include %} and {% embed %} when rendering an SDC. This technique is most often used by theme developers who override templates and compose a page using single directory components. A common scenario is expressing your design system as components in a theme, then overriding templates to use those components.
In this tutorial, we will:
- Reference a component from a parent Twig template file.
- Pass props and slot values to a component from that template.
- Decide when to use
{% include %}or{% embed %}based on the component's slot structure.
By the end of this tutorial, you’ll be able to embed a component into a Twig template and pass values to both its props and slots.
As a module developer, you output themed content from your module in the form of renderable arrays. When doing so, you can make use of single directory components (SDCs) by using the #type => 'component' render element type. This allows modules to dynamically select and configure a component based on configuration or specific PHP logic. You'll use this as the return value of a controller, or a configurable plugin related to display building, like custom blocks or field formatters. As an example, we'll author a custom block plugin that loads a specific node and outputs it using the card SDC we defined in a previous tutorial. We'll build a render array that supplies the values for the component's props and slots, and add some caching logic to the output.
In this tutorial, we will:
- Build a render array that targets an SDC via the
#componentproperty. - Pass data into the component's props and slots, and demonstrate optional
#propsAlterand#slotsAltercallbacks. - Validate the output and cache it properly.
By the end of this tutorial, you'll be able to render any SDC via a module's PHP code using a well-structured and cache-friendly render array.
One of the benefits of using Drupal single directory components is that Drupal automatically builds and attaches an asset library whenever it is used. Adding CSS styles and JavaScript interactivity to a single directory component (SDC) is as simple as dropping component-name.css and component-name.js files into the root directory of the component. Drupal detects these files, creates an asset library, and attaches it when the component is rendered. This means when you want to add additional CSS or JavaScript assets, you will override the asset library created for your component instead of defining a new one.
In this tutorial, we will:
- Add component-scoped CSS and JavaScript files.
- Learn how to override a component's existing asset library to add additional assets.
- Discuss how to integrate common front-end asset build tools (Gulp, Webpack, Vite, etc.) while working with Drupal single directory components.
By the end of this tutorial, you'll be able to attach CSS and JavaScript assets to an SDC and validate that they load only when the component is in use.
Drupal single directory components use Twig template files to define their HTML markup and how the values of props and slots are displayed. To discover available props and slots, read the component’s .component.yml file. When working with slots, you’ll often choose between rendering a slot as a Twig block ({% block %}) or interpolating a variable directly ({{ variable }}).
In this tutorial, you’ll:
- Add a card.twig file to an existing component directory.
- Read the associated card.component.yml schema to identify props and slots you can work with.
- Render props and slots wrapped in custom HTML markup.
By the end of this tutorial, you’ll be able to connect a Twig template to any SDC and render the props and slots passed into the component.
A Drupal single directory component (SDC) is Drupal's way of packaging the markup, metadata, styles, and behavior for a UI element in one self-contained folder inside a theme or module. This structure helps front-end developers and site builders keep all related files together for easier theming and reuse. A Drupal single directory component directory must be located in a specific place and its files named with a particular convention so that the system can discover it and use its assets.
In this tutorial, we'll:
- Show where Drupal discovers single directory components in your codebase.
- Explain the naming and organization conventions for Drupal single directory component directories and files.
- Outline key files for a component—both required and optional.
By the end of this tutorial, you'll be able to identify an SDC directory in a Drupal module or theme and know exactly what you're looking at.
Using Vite we can scaffold a stand-alone React application with modern tooling, instant dev-server startup, and hot module replacement. It's a great way to get started with React and works perfectly for decoupled apps that talk to Drupal's JSON:API. After creating the scaffold, we'll port code from previous tutorials to the new structure.
In this tutorial we'll:
- Use Vite to scaffold a new React project
- Refactor existing code into Vite's project structure
- Confirm that our code runs
By the end of this tutorial, you'll know what Vite is and how to get started using it for a decoupled React app.
Props and slots are the two ways that data can be provided to a single directory component (SDC). They are part of a component's schema definition, and are used to determine the names of variables passed to a component's template file. Props pass structured, validated data into a component, while slots allow us to inject flexible content such as HTML or nested components. Understanding when and how to use each ensures you can build reusable and adaptable components.
In this tutorial, we'll:
- Learn what props and slots are, and how they differ.
- Discuss how using one or the other impacts the developer experience and use of your components in a UI.
- Practice deciding when to use each for component design.
By the end of this tutorial, you'll know how to choose between props and slots when building components.
Overriding Single Directory Components (SDCs) allows you to safely customize the functionality and appearance of components provided by contrib modules or themes. Instead of editing the original files, copy a component into your theme, declare that it replaces the original, and then make the necessary adjustments. This approach ensures our changes are upgrade-safe and easy to maintain.
In this tutorial, we will:
- Copy an existing SDC into a theme.
- Use the
replaces:key in the component metadata to declare the override. - Modify the component Twig, CSS, or JavaScript and confirm the changes appear on our site.
By the end of this tutorial, you should be able to override SDCs safely and maintain your customizations in an upgrade-safe manner.
Learn how to generate menu links dynamically with plugin derivatives in a custom module. This tutorial walks through creating a single base menu link plugin definition and a deriver class that expands that definition into one menu link per content entity. The code will automatically generate links for all published basic pages, placing dynamic menu links in the main menu.
By the end of this tutorial, you should be able to:
- Understand which files you need in order to define menu link plugin derivatives, also known as dynamic menu links
- Create the necessary code to define menu link plugin derivatives for an example use case
This reference document contains a detailed list of available properties for the #[ContentEntityType] attribute in Drupal 11. The current documentation in the Drupal 11 code base lists, but doesn't always describe, each of these properties. Or, in many cases, the property is an associative array where the nested key/value pairs are important, but what they should be isn't well documented. So we've created this helpful reference. Most of the properties listed here will also apply to #[ConfigEntityType] attributes. These properties define the metadata and behavior of custom entity types.
In this tutorial, we'll:
- Look at an example of how to use
#[ContentEntityType]attributes. - Provide a comprehensive list of available properties and a description of each.
- Show detailed examples of using nested array properties like
handlers[].
By the end of this tutorial, you should be able to understand how and when to use any of the properties of a #[ContentEntityType] attribute in order to modify the behavior of a custom entity type.
Drupal stores the settings that define how a site behaves as configuration data. Everything from the site name to image styles, roles, and view definitions are stored as configuration. The Configuration API gives modules, themes, and installation profiles a consistent way to store, retrieve, update, and provide this configuration in a structured and portable way.
In this tutorial, we'll:
- Provide a high-level overview of the features of Drupal's Configuration API
- Link to related tutorials where you can learn more and get hands-on practice working with configuration data in code.
Bundle classes are a feature of the Drupal Entity API that let you attach PHP classes to individual bundles (for example, content types) so you can keep site-specific business logic close to the data it acts on. Bundle classes are a powerful way to encapsulate site-specific business logic and bridge user-configured fields and PHP logic based on those fields. In this tutorial, you will build a reusable bundle base class that adds a generic share behavior for all node types on a site and then extend it for a specific node type.
In this tutorial, we will:
- Explore a real-world problem that bundle classes can help you solve.
- Create a bundle base class for common share features shared across multiple node types.
- Implement a node-type-specific class that extends the base class with behavior tailored to the underlying content type.
By the end of this tutorial, you'll be able to use bundle classes to encapsulate per-bundle logic, assume the presence of UI-configured fields when appropriate, and register those classes so Drupal uses them at runtime.
Drupal recipes provide a new way to package and share reusable features across Drupal sites. Unlike traditional install profiles or distributions, recipes are applied once to add functionality and then step out of the way, leaving you with a standard Drupal site that you can customize freely.
In this tutorial, we will:
- Understand what Drupal recipes are and how they differ from install profiles and distributions
- Learn the four core properties that make recipes powerful: applied (not installed), shareable, non-locking, and composable
- Explore real-world scenarios where recipes solve common platform and agency challenges
By the end of this tutorial you'll be able to explain what Drupal recipes are, identify features in your projects that are good candidates for recipes, and articulate the value of recipes to stakeholders.
Recipes transform your Drupal site by adding features and configuration. After downloading (or authoring) a recipe it needs to be applied to your Drupal project. This is analogous to following the step-by-step instructions in a recipe to make a dish. Only, we're not performing the steps on our own, but instead we're using Drupal's tools to apply the recipe. Applying the recipe adds its features to your Drupal project. This requires establishing safe workflows to apply recipes, verify their effects, and roll back changes if needed.
In this tutorial, we will:
- Apply a recipe in a non-production environment using a feature branch workflow.
- Review configuration changes using Git and verify functionality in the UI.
- Understand how to roll back recipe changes if needed.
- Learn safe workflows for both developers and non-developers.
By the end of this tutorial, you'll be able to safely apply recipes to your projects, review their impact, and decide whether to keep or roll back the changes.
The built-in config actions in Drupal core cover most common scenarios. But sometimes you need custom operations specific to your feature or the configuration your module relies on. You can create custom config actions by defining them as plugins or by adding PHP attributes to a configuration entity class's methods. Let's implement a custom config action to toggle an SEO strict mode setting to learn how to extend recipes with domain-specific configuration operations and make them reusable across your projects.
In this tutorial, we will:
- Identify scenarios where custom config actions are warranted.
- Understand the two implementation patterns: plugins and attributed methods.
- Implement a custom config action in a module.
By the end of this tutorial, you'll be able to implement custom config actions that extend the configuration API provided to your recipes, making platform-specific operations reusable and declarative.