Skip to content

Drupal Contribution Environment: DDEV + the Workflow-Matched Add-on

When to Use

Use this when standing up a local environment for contribution work. The right add-on depends on which of the three workflows you are in.

Decision

Add-on For Install command
ddev/ddev-drupal-contrib (official) A single contrib module or theme ddev add-on get ddev/ddev-drupal-contrib
lussoluca/ddev-drupal-suite (community) Several interdependent contrib modules ddev add-on get lussoluca/ddev-drupal-suite
justafish/ddev-drupal-core-dev (community) Drupal core development ddev get justafish/ddev-drupal-core-dev

DDEV is the community standard — all drupal.org contribution docs and CI add-ons assume it.

Pattern

Contrib module/theme setup (ddev-drupal-contrib):

The key mental model: the module repo is the project root. web/ and vendor/ are generated by the add-on and .gitignore'd — never committed.

# 1. Clone the module repo (it IS the project root)
git clone git@git.drupalcode.org:project/my_module.git
cd my_module

# 2. Initialize DDEV
ddev config --project-type=drupal11 --docroot=web --php-version=8.3

# 3. Add the contrib add-on
ddev add-on get ddev/ddev-drupal-contrib

# 4. Start and install
ddev start
ddev poser            # builds composer.contrib.json + installs Drupal into web/
ddev symlink-project  # symlinks your module into web/modules/contrib/

# 5. Install Drupal
ddev drush si

Available commands after setup:

ddev phpcs
ddev phpstan
ddev phpunit web/modules/contrib/my_module/tests
ddev eslint
ddev stylelint

Switch core versions (multi-version testing):

# In .ddev/.env.web:
DRUPAL_CORE=^10

ddev restart  # auto-selects compatible PHP version
ddev poser    # rebuilds with the new core version

Core development setup (ddev-drupal-core-dev):

git clone git@git.drupalcode.org:project/drupal.git
cd drupal && git checkout main
ddev config --project-type=drupal11 --docroot=web
ddev get justafish/ddev-drupal-core-dev
ddev start && ddev drush si
ddev phpunit core/modules/<module>/tests

Do not install Drush into core with composer require — it pollutes core's composer.json.

Common Mistakes

  • Wrong: Committing web/ or vendor/Right: These are generated; gitignore them
  • Wrong: Installing Drush into core with composer requireRight: Use the core-dev add-on's wrappers
  • Wrong: Not running ddev poser after switching DRUPAL_CORERight: The Drupal install must be rebuilt for the new version
  • Wrong: Using a global add-on config across projects with different core versions → Right: Set DRUPAL_CORE per project

See Also