TYPO3 Content Blocks vs. FLUIDTEMPLATE with Data Processors: Choosing How to Render Custom Content
Deciding between TYPO3 Content Blocks and classic FLUIDTEMPLATE with data processors for custom content elements: constraints, a comparison table, trade-offs, and a validated card-element implementation.
26 Sept 2025, 03:22 UTC

The decision you're actually making
You need a custom structured content element — say, a card with a headline, body text, and an image — and TYPO3 offers two supported routes. The classic route wires a FLUIDTEMPLATE TypoScript object to a Fluid template, with data processors fetching related records. The newer route uses Content Blocks, where a single YAML file plus a Fluid template defines the whole element and TYPO3 generates the backend registration for you.
The short version: for new content element types on TYPO3 v12 or v13, Content Blocks is the lower-maintenance default. Keep FLUIDTEMPLATE plus data processors for page-level rendering and for existing elements that already work. The rest of this guide explains the constraints behind that recommendation and shows a concrete implementation you can validate.
Constraints that shape the choice
- Version line. Content Blocks shipped as an official extension for TYPO3 v12 and was integrated into the core in v13. The YAML schema and available field types changed between those releases, so examples must match your installed major version.
- Team skill set. The classic route assumes comfort with TCA (Table Configuration Array — TYPO3's schema for how records are edited and stored), PageTSconfig, and TypoScript. Content Blocks hides most of that.
- Upgrade horizon. Hand-written TCA and TypoScript wiring is a larger surface to review at every major upgrade. Declarative Content Blocks definitions track the core roadmap more closely.
- Complexity ceiling. If you need custom backend wizards, deeply nested IRRE (inline relational record editing) structures, or hook-driven behavior, the classic route gives you full control that Content Blocks' field vocabulary may not cover.
Supported options compared
| Aspect | Content Blocks (v12 ext / v13 core) | FLUIDTEMPLATE + data processors |
|---|---|---|
| Definition style | Declarative YAML + Fluid template | Imperative: TCA overrides, PageTSconfig, TypoScript |
| Boilerplate | Minimal; TCA, DB fields, wizard entry generated | You register CType, wizard item, and rendering yourself |
| Flexibility | Bounded by supported field types and conventions | Full: custom wizards, IRRE, hooks, arbitrary queries |
| Best fit | New structured content elements | Page templates, menus, legacy elements, edge cases |
| Upgrade risk | Lower; aligned with core direction | Higher; more manual surface to migrate |
| Documentation maturity | Newer; version-sensitive schema | Documented and stable for over a decade |
Trade-offs in practice
Content Blocks removes the three most error-prone chores: writing TCA overrides for tt_content, adding the element to the new-content-element wizard via PageTSconfig, and wiring the frontend rendering. In exchange, you accept its conventions — field naming, the field types it supports, and where templates live. For a typical card, teaser, or accordion element, that trade is clearly worth it.
The classic route earns its keep when Content Blocks can't express what you need, or when you're rendering a whole page rather than one element. Data processors such as DatabaseQueryProcessor, FilesProcessor, and the menu processors remain fully supported and are the right tool for assembling page-level data. Be aware that processor options like slide and relation collection behave subtly differently across versions — test empty-relation edge cases explicitly.
One rule matters regardless of route: do not mix both mechanisms for the same CType. Registering an element via Content Blocks and then overriding the same CType with hand-written TCA produces conflicting configuration that is painful to debug. Pick one registration mechanism per element.
Concrete implementation: a card element via Content Blocks
In a site package extension, create ContentBlocks/ContentElements/card/config.yaml (exact path and schema vary between v12 and v13 — check the docs for your version):
name: vendor/card
group: common
fields:
- identifier: header
type: Text
- identifier: text
type: Textarea
enableRichtext: true
- identifier: image
type: File
allowed: common-image-typesThen a Fluid template at the sibling templates location, e.g. templates/frontend.html:
<div class="card">
<h3>{data.header}</h3>
<f:format.html>{data.text}</f:format.html>
<f:if condition="{data.image}">
<f:image image="{data.image.0}" alt="{data.header}" />
</f:if>
</div>Flush caches so TYPO3 picks up the definition. From the command line, with a Composer-based install and sufficient filesystem permissions (the same user your deployment runs as):
vendor/bin/typo3 cache:flushTYPO3 generates the TCA, database fields, and wizard registration. Note that the image field shape (single file vs. collection) depends on the field configuration and version — verify the actual variable structure in your template rather than assuming image.0 works everywhere.
How to validate the result
- Backend registration. Open the page module, add a content element, and confirm "Card" appears in the new content element wizard under the expected group.
- Generated TCA. In the backend Configuration module (requires admin and the lowlevel system extension), inspect the
tt_contentTCA and confirm your fields exist and don't collide with any legacy overrides. - Database schema. Run the Install Tool's database schema comparison to confirm the generated columns match the YAML definition.
- Frontend rendering. Create a test element on a scratch page, render it, and diff the HTML output against your Fluid template's expectations — including the empty-image case.
Limitations and when to stay classic
The YAML schema is version-sensitive: a definition written for the v12 extension may need adjustments under v13 core integration, so review the v13 upgrade notes before migrating an existing site. Content Blocks also doesn't cover every backend customization; if your element needs bespoke wizard logic or complex inline relations, hand-written TCA remains the supported path. Finally, avoid investing in deprecated patterns — rendering built on old css_styled_content or heavy CONTENT-cObject setups increases your migration cost to v13 and beyond regardless of which route you choose for new work.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.