Starting constraint
TYPO3 had been the corporate CMS for over a decade. Editors knew the keyboard. The site was plugged into legal review, into translations, and into a brand book that pre-dated most current employees.
The migration was not a redesign. It had to keep visual identity, keep every URL, keep the multilingual matrix, and keep the editorial calendar moving while the platform changed underneath.
Content model audit
The first month was spent reading the TYPO3 page tree, not writing code. Each TYPO3 content element had to be classified: native equivalent in WordPress core, candidate for ACF or block pattern, candidate for archival as static content, or candidate for retirement.
The audit produced a one-to-one map. Without that map, a migration becomes a guess.
Content element to block map
The audit produced a one-to-one map. The rows below are the classification rules used on this engagement; exact CType inventory counts remain confidential.
| TYPO3 source (typical) | Classification | WordPress destination | Notes |
|---|---|---|---|
| Text / header / bodytext | Native equivalent | Core paragraph, heading, list, quote | Clean HTML; strip TypoScript wrappers |
| Image / textpic / media | Native + media | Core image / gallery + media library | FAL to uploads; regenerate sizes pre-cutover |
| Bullet / table | Native equivalent | Core list / table | Prefer core over custom HTML |
| Accordion / tabs / custom CE | Pattern or ACF | Block pattern or ACF + InnerBlocks | Name patterns in editors' language |
| News / press / jobs / events / people records | Structured | CPT + taxonomies (+ ACF) | Page tree is not category; model permissions separately |
| Shared header/footer / teaser snippets | Global | Synced patterns or template parts | Avoid lost multilingual fragment overlays |
| TypoScript-only layout chrome | Retire or rebuild | Theme / FSE template | Do not import TypoScript |
| Obsolete CE with no traffic | Retire | Archive or drop | Document retirement in the map |
| Unclear / Extbase-heavy | Escalation | Custom plugin or CPT + REST | Same class as the three macros replaced here |
URL and schema continuity
Every URL was preserved. Where TYPO3 had RealURL or path segments that no longer fit, a 301 redirect map was generated and validated before launch. Multilingual variants stayed at the same paths.
Article and Organization schema migrated with the content. Hreflang continuity was checked per locale before DNS cutover.
Redirect map checklist
Where TYPO3 RealURL or path segments no longer fit, a 301 redirect map was generated and validated before launch. Multilingual variants stayed on the same paths whenever the content model allowed it.
| Column | Required | Purpose |
|---|---|---|
| source_url | yes | Full legacy path (incl. locale prefix / RealURL segment) |
| target_url | yes | WordPress permalink after model map |
| status | yes | 301 default; rare 410 only for intentional retirement |
| locale | yes | en / de / … matching hreflang set |
| hreflang_group_id | yes | Ties language siblings so one locale is not orphaned |
| realurl_note | if needed | Why path could not stay identical |
| organic_traffic | recommended | Flag rows with GSC/analytics hits for priority QA |
| validated_on_staging | yes | Checkbox / date before DNS |
| owner | optional | Who signed the row |
Editor onboarding
Editors had a Friday training, a Monday parallel publishing day, and a Wednesday cutover. The block editor was localised, the patterns were named in the language editors actually used, and a small custom plugin replaced the three TYPO3 macros that mattered most.
Editors kept the existing brand language while the CMS changed.
Outcome bands
Exact numbers are confidential. The publishable result: editorial throughput improved within the first month, page weight on the corporate template family dropped meaningfully, and search visibility for the German-language head terms held through cutover with no recovery dip.
Treat TYPO3 to WordPress as a content model migration. Audit the model before building importers.