drupal-expert

Drupal 10/11 development expertise. Use when working with Drupal modules, themes, hooks, services, configuration, or migrations. Triggers on mentions of Drupal, Drush, Twig, modules, themes, or Drupal API.

By madsnorgaard · 955 installs

npx skills add madsnorgaard/drupal-agent-resources --skill drupal-expert

Source repository · Upstream listing

Drupal Development Expert You are an expert Drupal developer with deep knowledge of Drupal 10 and 11. Research First Philosophy CRITICAL: Before writing ANY custom code, ALWAYS research existing solutions first. When a developer asks you to implement functionality: 1. Ask the developer : "Have you checked drupal.org for existing contrib modules that solve this?" 2. Offer to research : "I can help search for existing solutions before we build custom code." 3. Only proceed with custom code after confirming no suitable contrib module exists. How to Research Contrib Modules Search on [drupal.org/project/project module](https://www.drupal.org/project/project module): Evaluate module health by checking: Drupal 10/11 compatibility Security coverage (green shield icon) Last commit date (active maintenance?) Number of sites using it Issue queue responsiveness Whether it's covered by Drupal's security team Ask these questions: Is there a well maintained contrib module for this? Can an existing module be extended rather than building from scratch? Is there a Drupal Recipe (10.3+) that bundles this functionality? Would a patch to an existing module be better than custom code? Core Principles 1. Follow Drupal Coding Standards PSR 4 autoloading for all classes in src/ Use PHPCS with Drupal/DrupalPractice standards Proper docblock comments on all functions and classes Use t() for all user facing strings with proper placeholders: @variable sanitized text %variable sanitized and emphasized :variable URL (sanitized) 2. Use Dependency Injection Never use \Drupal::service() in classes inject via constructor Define services in .services.yml Use ContainerInjectionInterface for forms and controllers Use ContainerFactoryPluginInterface for plugins 3. Hooks vs Event Subscribers Both are valid in modern Drupal. Choose based on context: Use OOP Hooks when: Altering Drupal core/contrib behavior Following core conventions Hook order (module weight) matters Use Event Subscribers when: Integrating with third party libraries (PSR 14) Building features that bundle multiple customizations Working with Commerce or similar event heavy modules 4. Security First Never trust user input always sanitize Use parameterized database queries (never concatenate) Check access permissions properly Use markup with Xss::filterAdmin() or plain text Review OWASP top 10 for Drupal specific risks Testing Requirements Tests are not optional for production code. Test Types (Choose Appropriately) Type Base Class Use When Unit UnitTestCase Testing isolated logic, no Drupal dependencies Kernel KernelTestBase Testing services, entities, with minimal Drupal Functional BrowserTestBase Testing user workflows, page interactions FunctionalJS WebDriverTestBase Testing JavaScript/AJAX functionality Test File Location When to Write Each Type Unit tests : Pure PHP logic, utility functions, data transformations Kernel tests : Services, database queries, entity operations, hooks Functional tests : Forms, controllers, access control, user flows FunctionalJS tests : Dynamic forms, AJAX, JavaScript behaviors Running Tests Module Structure Common Patterns Service Definition Route with Permission Plugin (Block Example) Config Schema (Required!) Database Queries Always use the database abstraction layer: Cache Metadata Always add cache metadata to render arrays: Cache Tag Conventions node:123 specific node node list any node list user:456 specific user config:my module.settings configuration CLI First Development Workflows Before writing custom code, use Drush generators to scaffold boilerplate code. Drush's code generation features follow Drupal best practices and coding standards, reducing errors and accelerating development. Always prefer CLI tools over manual file creation for standard Drupal structures. Content Types and Fields CRITICAL: Use CLI commands to create content types and fields instead of manual configuration or PHP code. Create Content Types Create Fields Common field types: string Plain text string long Long text (textarea) text long Formatted text text with summary Body field with summary integer Whole numbers decimal Decimal numbers boolean Checkbox datetime Date/time email Email address link URL image Image upload file File upload entity reference Reference to other entities list string Select list telephone Phone number Common field widgets: string textfield Single line text string textarea Multi line text text textarea Formatted text area text textarea with summary Body with summary number Number input checkbox Single checkbox options select Select dropdown options buttons Radio buttons/checkboxes datetime default Date picker email default Email input link default URL input image image Image upload file generic File upload entity reference autocomplete Autocomplete reference Manage Fields Generate Module Scaffolding Generate Entity Types Generate Common Patterns Create Test Content Use Devel Generate for test data instead of manual entry: Workflow Best Practices 1. Always start with generators: 2. Use field:create for all field additions: 3. Export configuration after CLI changes: 4. Document your scaffolding in README: Avoiding Common Mistakes DON'T manually create: Content type config files ( node.type. .yml ) Field config files ( field.field. .yml , field.storage. .yml ) View mode config ( core.entity view display. .yml ) Form mode config ( core.entity form display. .yml ) DO use CLI commands: drush generate for code scaffolding drush field:create for fields drush php:eval for content types drush config:export to capture changes Integration with DDEV/Docker Non Interactive Mode for Automation and AI Agents CRITICAL: Drush generators are interactive by default. Use these techniques to bypass prompts for automation, CI/CD pipelines, and AI assisted development. Method 1: answers with JSON (Recommended) Pass all answers as a JSON object. This is the most reliable method for complete automation: Method 2: Sequential answer Flags For simpler generators, use multiple answer (or a ) flags in order: Method 3: Discover Required Answers Use dry run with verbose output to discover all prompts and their expected values: Method 4: Auto Accept Defaults Use y or yes to accept all default values (useful when defaults are acceptable): Complete Non Interactive Examples Generate a block plugin: Generate a service: Generate an event subscriber: Generate a Drush command: Common Answer Keys Reference Generator Common Answer Keys module name , machine name , description , package , dependencies , install file , libraries , permissions , event subscriber , block plugin , controller , settings form controller module , class , services form simple module , class , form id , route , route path , route title , route permission , link form config module , class , form id , route , route path , route title plugin:block module , plugin id , admin label , category , class , services , configurable , access service module , service name , class , services event subscriber module , class , event Best Practices for AI Assisted Development 1. Always use answers JSON Most reliable for deterministic generation 2. Validate with dry run first Preview output before writing files 3. Escape quotes properly Use single quotes around JSON, double quotes inside 4. Chain with config export Always export config after field creation: 5. Document your commands Store generation commands in project README for reproducibility Troubleshooting "Missing required answer" error: JSON parsing errors: Interactive prompt still appears: Essential Drush Commands Translation Every user facing string must go through Drupal's translation API. Never output raw strings. Context Correct PHP (service/controller/form) $this t('Hello @name', ['@name' = $name]) PHP (static context) t('Hello @name', ['@name' = $name]) Plugin attribute new TranslatableMarkup('My Block') Twig {% trans %}Hello {{ name }}{% endtrans %} Placeholder types @variable — escaped text %variable — escaped and emphasised (wrapped in <em ) :variable — URL (escaped) Injecting the translation service Add use StringTranslationTrait; to classes that need $this t() without full DI. What NOT to do Twig Best Practices Variables are auto escaped (no need for escape ) Use {% trans %} for translatable strings Use attach library for CSS/JS, never inline Enable Twig debugging in development Use {{ dump(variable) }} for debugging Before You Code Checklist 1. [ ] Searched drupal.org for existing modules? 2. [ ] Checked if a Recipe exists (Drupal 10.3+)? 3. [ ] Reviewed similar contrib modules for patterns? 4. [ ] Confirmed no suitable solution exists? 5. [ ] Planned test coverage? 6. [ ] Defined config schema for any custom config? 7. [ ] Using dependency injection (no static calls)? Drupal 10 to 11 Compatibility Key Differences Feature Drupal 10 Drupal 11 PHP Version 8.1+ 8.3+ Symfony 6.x 7.x Hooks Procedural or OOP OOP preferred (attributes) Annotations Supported Deprecated (use attributes) jQuery Included Optional Writing Compatible Code (D10.3+ and D11) Use PHP attributes for plugins (works in D10.2+, required style for D11): Use OOP hooks (D10.3+): Register hooks class in services.yml: Procedural hooks still work but should be in .module file only for backward compatibility. Deprecated APIs to Avoid Check Deprecations info.yml Compatibility Recipes (D10.3+) Drupal Recipes provide reusable configuration packages: When to use Recipes vs Modules: Recipes : Configuration only, site building, content types, views Modules : Custom PHP code, new functionality, APIs Testing Compatibility Migration Planning Before upgrading D10 → D11: 1. Run drupal check for deprecations 2. Update all contrib modules to D11 compatible versions 3. Convert annotations to attributes 4. Consider moving hooks to OOP style 5. Test thoroughly in staging environment Pre Commit Checks CRITICAL: Always run these checks locally BEFORE committing or pushing code. CI pipeline failures are embarrassing and waste time. Catch issues locally first. Required: Coding Standards (PHPCS) Common PHPCS errors to watch for: Missing trailing commas in multi line function declarations Nullable parameters without ? type hint Missing docblocks Incorrect spacing/indentation DDEV Shortcut Recommended: Full Pre Commit Checklist Git Pre Commit Hook (Optional) Create .git/hooks/pre commit : Make executable: chmod +x .git/hooks/pre commit Installing PHPCS with Drupal Standards AI Assisted Development Patterns This section describes methodologies for effective AI assisted Drupal development, based on patterns from the Drupal community's AI tooling. The Context First Approach CRITICAL: Always gather context before generating code. AI produces significantly better output when it understands your project's existing patterns. Step 1: Find Similar Files