Default Content Deploy
A content deployment solution for Drupal that enables teams to export and import content continuously via JSON files without database transfers.
default_content_deploy
Install
composer require 'drupal/default_content_deploy:^2.1'
Overview
Default Content Deploy (DCD) provides a comprehensive content deployment solution for Drupal, allowing development teams to export and deploy all site content via Git. This eliminates the need to transfer databases between environments (local, staging, production).
The module serializes entities to JSON files using the HAL (Hypertext Application Language) format and stores them in a configurable content directory. Content can be exported individually, by entity type, with all references, or the entire site at once. Imports intelligently compare timestamps to only update content that has changed.
DCD is particularly valuable for CI/CD workflows where content needs to be deployed automatically alongside code changes. It supports incremental imports, force overrides, and can handle complex entity relationships including Layout Builder blocks and embedded media in text fields.
Features
- Export individual entities, entity types, or entire site content to JSON files
- Import content with intelligent timestamp-based comparison to avoid overwriting newer content
- Export entities with all their references recursively (media, files, taxonomy terms, users, etc.)
- Support for Layout Builder inline blocks and referenced block content
- Export dependencies embedded in processed text fields (images, media, entities in CKEditor content)
- Download exported content as a compressed tar.gz archive via the admin UI
- Upload and import content from tar.gz archive files
- Force override option to revert all content to the state defined in export files
- Drush commands for all operations enabling CI/CD automation
- Batch processing for large content sets with progress tracking
- Incremental import mode that skips unchanged content based on timestamps
- Event system for customizing export/import behavior via event subscribers
- Skip specific entity types from export/import operations
- Delete content during import (mark exported entities for deletion)
- Preserve entity IDs option for specific deployment scenarios
- Search API integration submodule for tracking and incremental exports
- Cron-based garbage collection for orphaned batch items
Use Cases
Development Team Content Synchronization
Multiple developers working on a project can export content to the Git repository. Each developer exports their changes with 'drush dcdes', commits the JSON files, and others import with 'drush dcdi' after pulling. This eliminates the need to share database dumps and ensures content changes are version controlled alongside code.
CI/CD Automated Content Deployment
In a continuous deployment pipeline, content can be automatically deployed alongside code. The deploy script includes: git pull, drush updb -y, drush cim -y, drush cr, drush dcdi -y. This ensures staging and production environments have consistent content without manual intervention.
Default Content for Site Installation
Package default content with a custom installation profile or module. Export initial content once, commit to the repository, and have it imported automatically on every fresh installation. Perfect for demo sites, starter kits, or distribution packages.
Content Staging Workflow
Content editors create content on a staging environment. Using the Export UI or Drush commands, content is exported to files. After review, these files are deployed to production via Git, where they're imported. This provides a controlled content promotion workflow.
Site Migration and Backup
Export the entire site's content with 'drush dcdes' before major updates or migrations. The JSON files serve as a portable backup that can be imported into any Drupal installation with matching configuration, regardless of database differences.
Incremental Content Sync with Search API
Using the Search API submodule, content changes are automatically tracked. Only modified entities are exported, making it efficient for sites with large amounts of content. The Search API backend handles the complexity of determining what needs to be exported.
Tips
- Place the content directory outside the document root for security (e.g., ../content relative to web root)
- Use --verbose flag with Drush commands to see detailed progress and entity-level information during import/export
- For large sites, use the --changes-since option to export only recently modified content
- Export users first when setting up a new environment to ensure UUID synchronization for admin and anonymous users
- The _thumbs folder contains lightweight metadata files for faster incremental import scanning
- Use 'drush dcd-entity-list' to see all available entity types before exporting
- Commit exported content files to Git with meaningful commit messages for traceability
- Test imports on a staging environment before deploying to production
- The Search API submodule provides automatic export on entity save, ideal for continuous content export workflows
Technical Details
Admin Pages 3
/admin/config/development/dcd
Configure global settings for content export and import operations including the content directory path, entity types to skip, and serialization options.
/admin/config/development/dcd/import
Import content from JSON files stored in the content directory or from an uploaded archive file. Equivalent to drush dcdi command.
/admin/config/development/dcd/export
Export content to JSON files in the content directory or download as a compressed archive. Equivalent to drush dcde/dcder/dcdes commands.
Permissions 2
Hooks 2
hook_hal_type_uri_alter
Alters the HAL type URI during serialization. DCD uses this to create portable URIs in format [ENTITY_TYPE]/[BUNDLE].
hook_hal_relation_uri_alter
Alters the HAL relation URI during serialization. DCD uses this to create portable URIs in format relation/[ENTITY_TYPE]/[BUNDLE]/[FIELD].
Drush Commands 9
drush default-content-deploy:export <entity_type>
Exports a single entity or group of entities without references. Exports entities as JSON files to the content directory.
drush default-content-deploy:export-with-references <entity_type>
Exports entities along with all their referenced entities recursively. Includes media, files, taxonomy terms, users, and other referenced content.
drush default-content-deploy:export-site
Exports all content on the entire site. Useful for full site backups or initial content deployment setup.
drush default-content-deploy:import
Imports content from JSON files in the content directory. Creates new entities or updates existing ones based on UUID matching.
drush default-content-deploy:uuid-info <entity_type> <id>
Displays the UUID value of a specific entity. Useful for identifying entities for export.
drush default-content-deploy:entity-list
Displays all content entity types available on the site. Useful for determining valid entity_type arguments.
drush default-content-deploy:get-last-import-timestamp
Get the last import timestamp stored in state for a content folder. Used for incremental import tracking.
drush default-content-deploy:set-last-import-timestamp <timestamp>
Set the last import timestamp in state for a content folder. Useful for resetting incremental import state.
drush default-content-deploy:sync-thumbs
Synchronize the thumbs (metadata) folder from the content directory. Creates optimized metadata files for faster incremental imports.
Troubleshooting 7
Apply the patch from https://www.drupal.org/files/issues/2023-04-05/2904423-90.patch to address the HAL module issue with translated fields.
Apply the core patch from https://www.drupal.org/project/drupal/issues/2329253 to preserve entity timestamps. Drupal 11 includes this fix natively.
Move the content directory outside the document root (recommended) or add .htaccess (Apache) or nginx location rules to deny access to JSON files in the content directory.
Use 'drush dcder' instead of 'drush dcde' to export with references. Check that the referenced entity types are not listed in 'skip_entity_types' configuration.
The import compares timestamps and skips entities where the file is older than the database. Use --force-override flag to import regardless of timestamps.
By design, DCD uses UUIDs for entity identification. Entity IDs may change during import. If preserving IDs is critical, use the --preserve-ids flag (may cause conflicts with existing entities).
The better_normalizers module is incompatible with DCD. Remove it before using Default Content Deploy.
Security Notes 5
- Exported JSON files may contain sensitive data. Always place the content directory outside the document root or protect it with web server configuration.
- The import permission allows overwriting any existing content. Grant this permission only to trusted administrators.
- User password hashes are included in user entity exports. Ensure the content directory is not publicly accessible.
- When importing from uploaded archives, validate the source to prevent importing malicious content.
- The module operates with administrator privileges during import/export to access all entity data.