From drupal-boost
Scaffolds Drupal 11 modules with services, plugins, controllers, forms, routing, event subscribers, OOP Hook attributes, Entity/Field API, Queue/Batch API. Use when creating a new module, adding a service, creating a plugin type, implementing a hook, or building a custom entity.
npx claudepluginhub abderrahimghazali/drupal-boostThis skill is limited to using the following tools:
You are helping build or extend a Drupal 11 custom module. Follow these patterns precisely.
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
You are helping build or extend a Drupal 11 custom module. Follow these patterns precisely.
modules/custom/MODULE_NAME/
├── MODULE_NAME.info.yml # Required: module metadata
├── MODULE_NAME.module # Optional: procedural hooks (prefer OOP)
├── MODULE_NAME.install # Optional: install/update hooks
├── MODULE_NAME.services.yml # Services and DI
├── MODULE_NAME.routing.yml # Routes
├── MODULE_NAME.permissions.yml # Permissions
├── MODULE_NAME.links.menu.yml # Menu links
├── MODULE_NAME.links.task.yml # Local tasks (tabs)
├── MODULE_NAME.links.action.yml # Local actions
├── MODULE_NAME.libraries.yml # CSS/JS libraries
├── src/
│ ├── Controller/ # Route controllers
│ ├── Form/ # Forms
│ ├── Plugin/ # Plugins (Block, Field, etc.)
│ ├── Entity/ # Entity types
│ ├── Service/ # Custom services
│ ├── EventSubscriber/ # Event subscribers
│ ├── Hook/ # OOP Hook implementations (Drupal 11.1+)
│ ├── Access/ # Custom access checkers
│ └── Commands/ # Drush commands
├── config/
│ ├── install/ # Default config installed with module
│ ├── optional/ # Config installed if dependencies met
│ └── schema/ # Config schema definitions
└── templates/ # Twig templates
name: 'Module Name'
type: module
description: 'Brief description of the module.'
core_version_requirement: ^10 || ^11
package: Custom
dependencies:
- drupal:node
- drupal:user
Always use DI. Define services in MODULE_NAME.services.yml:
services:
MODULE_NAME.my_service:
class: Drupal\MODULE_NAME\Service\MyService
arguments: ['@entity_type.manager', '@current_user', '@logger.factory']
Inject in classes via constructor:
public function __construct(
private readonly EntityTypeManagerInterface $entityTypeManager,
private readonly AccountProxyInterface $currentUser,
private readonly LoggerChannelFactoryInterface $loggerFactory,
) {}
Use ContainerInjectionInterface for controllers, ContainerFactoryPluginInterface for plugins.
Preferred over procedural hooks:
namespace Drupal\MODULE_NAME\Hook;
use Drupal\Core\Hook\Attribute\Hook;
class ModuleHooks {
#[Hook('entity_insert')]
public function onEntityInsert(EntityInterface $entity): void {
// Handle entity insert.
}
#[Hook('form_alter')]
public function onFormAlter(array &$form, FormStateInterface $form_state, string $form_id): void {
// Alter forms.
}
}
Hook ordering (Drupal 11.2+):
#[Hook('entity_presave', order: Order::First)]
#[Hook('entity_presave', order: new OrderBefore(['other_module']))]
MODULE_NAME.my_page:
path: '/my-path/{node}'
defaults:
_controller: '\Drupal\MODULE_NAME\Controller\MyController::content'
_title: 'My Page'
requirements:
_permission: 'access content'
options:
parameters:
node:
type: entity:node
Extend FormBase for custom forms, ConfigFormBase for settings forms:
class MyForm extends FormBase {
public function getFormId(): string { return 'my_form'; }
public function buildForm(array $form, FormStateInterface $form_state): array { ... }
public function validateForm(array &$form, FormStateInterface $form_state): void { ... }
public function submitForm(array &$form, FormStateInterface $form_state): void { ... }
}
Block plugin example:
#[Block(
id: "my_block",
admin_label: new TranslatableMarkup("My Block"),
category: new TranslatableMarkup("Custom"),
)]
class MyBlock extends BlockBase implements ContainerFactoryPluginInterface {
// Inject services via create() and __construct()
}
src/ classes — never \Drupal::service()#cache => tags, contexts, max-age)->accessCheck(TRUE) on entity queries$this->t() for translations in classesDrupal\MODULE_NAME\* maps to src/*Read reference files in reference/ for detailed API patterns:
reference/service-patterns.md for DI patternsreference/plugin-types.md for plugin system detailsreference/hook-attributes.md for OOP hooksreference/entity-field-api.md for entity/field development