Home › Drupal › Drupal 11 module development CLAUDE.md

Drupal 11 module development CLAUDE.md

CLAUDE.md for Drupal 11 sites and custom modules: Composer, Drush, services and dependency injection, config management, and PHPUnit.

Claude Code (CLAUDE.md)Drupal

How to use

Save this as CLAUDE.md in your repository root, commit it, and your agent will pick it up automatically. Edit the commands to match your project.

Note: Review and test before use. Provided as is, without warranty. See Terms.

CLAUDE.mdDownload  
# CLAUDE.md: Drupal 11 site

## Commands
- `composer install` · `drush cr` (rebuild caches) · `drush updb -y` · `drush cim -y` / `drush cex -y`
- Code standards: `vendor/bin/phpcs --standard=Drupal,DrupalPractice web/modules/custom`
- Static analysis: `vendor/bin/phpstan analyse web/modules/custom` (with `mglaman/phpstan-drupal`)
- Tests: `vendor/bin/phpunit -c web/core web/modules/custom/<module>`
- Local env is DDEV if `.ddev/` exists: prefix commands with `ddev` (e.g. `ddev drush cr`).

## Code map
- Custom code only in `web/modules/custom/` and `web/themes/custom/`. Never edit `web/core/` or contrib modules; use patches via `cweagans/composer-patches` in `composer.json`.
- Config lives in `config/sync/`; changes made in the UI must be exported with `drush cex` and committed.

## Conventions
- Modules: `<module>.info.yml` with `core_version_requirement: ^11`, services in `<module>.services.yml`, routes in `<module>.routing.yml` with explicit `_permission` or `_custom_access`.
- Use dependency injection: services via constructor injection; controllers and forms implement `create(ContainerInterface $container)`. No `\Drupal::service()` in classes (OK in `.module` hooks only when unavoidable).
- Prefer OOP hooks with `#[Hook('hook_name')]` attributes in `src/Hook/` classes over procedural `.module` functions where the core version supports them.
- Plugins (blocks, field formatters, queue workers) use PHP attributes, not annotations, for new code.
- Entity queries call `->accessCheck(TRUE)` (or deliberately FALSE with a comment).
- Render arrays with `#cache` metadata (tags, contexts, max-age). Don't disable caching to "fix" stale output.
- Output escaping is automatic in Twig; never use `|raw` on user input. Translate strings with `$this->t()` / `{{ 'Text'|t }}`.
- Schema changes go in `hook_update_N()` or post-update functions, never manual SQL.

## Done
phpcs and phpstan are clean, tests pass, `drush cr` runs, and `drush cex` shows no unexpected config diff.

More: all Drupal rules · all Claude Code (CLAUDE.md) rules

Related rules

WordPress plugin CLAUDE.md

CLAUDE.md for WordPress plugin development: prefixes, hooks, nonces and capabilities, sanitizing, escaping, and wp-env.

Claude Code (CLAUDE.md)WordPress

Payload CMS 3 + Next.js Cursor rules

Cursor rules for Payload CMS 3 inside Next.js: collections and fields config, access control, hooks, Local API, generated types and migrations.

CursorPayload CMS

Sanity Studio + GROQ AGENTS.md

AGENTS.md for Sanity projects: schema types with defineType, typed GROQ queries via TypeGen, Portable Text, previews, and safe content migrations.

AGENTS.mdSanity

Shopify app AGENTS.md

AGENTS.md for Shopify apps built with Shopify CLI and the React Router template: auth, GraphQL Admin API, and webhooks.

AGENTS.mdShopify

Shopify Liquid theme rules

Cursor rules for Shopify Online Store 2.0 themes: sections and blocks, JSON templates, Liquid performance, Theme Check.

CursorShopify

WordPress block theme & blocks rules

Cursor rules for WordPress block themes and custom blocks: theme.json v3, block.json, patterns, and @wordpress/scripts.

CursorWordPress

Get the best new AI prompts every week

One short email a week: the best new prompts and rules for ChatGPT, Claude, Gemini, Midjourney, Cursor and more, plus what changed in the tools. Free, unsubscribe anytime.

Finishes on our newsletter page at beehiiv (opens in a new tab). Or subscribe directly.