contentful_migration
Contentful Migration moves a Contentful space export into Drupal using the core Migrate API, handling the parts a YAML-only migration can't: Rich Text, embedded entries and assets, media, and cross-reference links.
It is a runtime, not a fixed content model. Every Contentful space is modelled differently, so the module executes per-space migration YAML rather than shipping one schema. The worked migrations in migrations/examples/ are templates you adapt to your space. (The same mapping YAML can optionally be generated by companion content-model analysis tooling.)
What it does
- Rich Text AST → HTML with embedded entry/asset resolution. The contentful/rich-text library's default renderers emit Contentful-id placeholders (visible garbage) or silently drop unknown nodes. This module owns the full renderer list, resolves sys.id references to the already-migrated Drupal entities, and emits clean <drupal-entity-embed> / <drupal-media> tokens — ending in a logging catch-all that never silently empties.
- Assets → Media, staging files into Media entities and de-duplicating identical bytes by SHA-256 (self-contained — no migrate_file_to_media).
- References → internal links, rewriting Contentful entry/asset references to alias-safe entity: link URIs.
- Locale flattening and a two-pass migration (entities first, bodies second) so embeds resolve against already-migrated content.
- Multi-value Paragraph references via the idiomatic core #2890844 workaround.
- A drush contentful:export command wraps the contentful-export CLI (assets included) to stage a space's JSON + asset binaries ready for migration; the management token is read from the CONTENTFUL_MANAGEMENT_TOKEN environment variable, never the process argv.
Migrated content lands in standard Drupal entities (nodes, Paragraphs, Media, menus), so you can present it however you like — decoupled, recoupled, or traditional.
Project status
Early development. The migration runtime and the contentful:export Drush command are built and covered by unit and kernel tests, including a real two-pass Migrate run that resolves embeds and stages assets to Media. On the roadmap: ready-made presentation-mode profiles and inline Rich Text hyperlink rewriting.
This project is not yet covered by Drupal's security advisory policy.
Requirements
- Drupal 11
- PHP 8.3+
- Core Migrate (the only hard dependency)
- contentful/rich-text ^4.0 (pulled in via Composer)
Paragraphs, Media, and migrate_plus are needed only when your mapping uses them — see the README.
Getting started
composer require 'drupal/contentful_migration:1.0.x-dev' drush en contentful_migration
Then stage your space and adapt the example migrations:
CONTENTFUL_MANAGEMENT_TOKEN=cfpat-… drush contentful:export --space-id=YOUR_SPACE # edit migrations/examples/ to match your content model
Not in scope
One-way migration only (not live bidirectional sync). Does not generate a theme, preserve Contentful authorship/edit history, or migrate Contentful functional config (webhooks, roles, UI extensions, SSO).