Anyone who builds TYPO3 extensions knows the drill: a single new database field means edits in five separate places, ext_tables.sql, the TCA configuration, the Domain Model, the Repository, and the Fluid template. It is time-consuming, it breeds inconsistencies, and it turns maintenance into a test of patience.
The good news: two modern approaches do away with this overhead. Content Blocks handle declarative data structures and PHP 8.4 Property Hooks keep Domain Models lean. Together, they cut boilerplate by up to 80%.
Terminology
Before we dive in, a quick clarification of terms:
| Term | Meaning |
|---|---|
| Content Blocks | The extension that generates code for the TYPO3 Core API |
| Content Block | A single configuration unit defining exactly one Content Type |
| Content Type | An entity in TYPO3 with defined fields and behaviour |
| Content Element | Content Type with frontend rendering (in tt_content) |
| Record Type | Generic Content Type for structured data |
| Page Type | Content Type defining the behaviour of a web page |
| File Type | Extended metadata for files (in sys_file_reference) |
Table of Contents
Terminology
Clarification of Content Blocks terms
Effort & Savings
Relative effort, reduction
Conclusion
Act now, profit later
What You Actually Save
First, an overview: what do you gain by switching to Content Blocks?
Effort: Classic vs. Content Blocks + PHP 8.4
| task | ContentBlocks | Classic |
|---|---|---|
| New Field | 20 | 100 |
| TCA Config | 1 | 100 |
| SQL Schema | 1 | 100 |
| Content Element | 10 | 100 |
| Change Field Type | 5 | 100 |
| Getter/Setter | 15 | 100 |
Relative effort in percent – 1% represents fully automated (no manual effort). Lower is better.
| Task | Classic | Content Blocks | Reduction |
|---|---|---|---|
| Add new field | 4-5 files | 1 YAML file | ~80% |
| TCA configuration | Manual (50-100 lines) | Automatically generated | 100% |
| SQL schema | Maintain ext_tables.sql | Automatically generated | 100% |
| New Content Element | 30-60 mins | < 5 mins (CLI) | ~90% |
| Change field type | TCA + SQL + Model | 1 line of YAML | ~95% |
| Getter/Setter (PHP 8.4) | ~20 lines/field | Property Hook (3 lines) | ~85% |
A typical Content Element with 5 fields shrinks from ~300 lines of boilerplate to ~40 lines of declarative YAML. Maintenance becomes predictable, and the scope for errors drops dramatically.
Installing Content Blocks
Installation takes just a few steps, via Composer or the Extension Manager, depending on your setup.
In Classic Mode, you must block web server access to the ContentBlocks folder. Otherwise, internal configuration files become publicly accessible.
Creating New Content Types via CLI
The make:content-block command, inspired by the well-established EXT:make extension, scaffolds the complete base structure for a new Content Block in seconds.
Interactive Mode
Direct Invocation with Parameters
Available Options
| Option | Description | Example |
|---|---|---|
| --content-type | Type of Content Type | content-element, page-type, record-type |
| --vendor | Vendor name (lowercase, kebab-case) | webconsulting |
| --name | Name of the Content Block | team-member |
| --extension | Host extension for the Content Block | my_sitepackage |
| --title | Display name in the backend | Team Member |
| --skeleton-path | Path to custom templates | content-blocks-skeleton |
After Creation
With --skeleton-path, you can supply your own templates. Ideal for teams that want to enforce consistent structures across all Content Blocks.
The Problem: Fragmented Truth
In classic TYPO3 extensions, the definition of a single field is scattered across several files:
Traditional: One field, five adjustments
Every change has to be synchronised by hand. Miss one spot, and the database schema and backend form fall out of step, a classic breeding ground for bugs.
The Solution: YAML as a Single Source of Truth
With the Content Blocks extension, you define structure, type, and validation in a single place. From that, the extension automatically generates:
Database columns
Automatically creates the SQL structure from your field definitions.
TCA configuration
Derives backend forms directly from the YAML definition.
Frontend data
Provides structured data for Fluid templates, with no manual mapping.
The Key Advantage
| Feature | Classic | Content Blocks |
|---|---|---|
| Points of change per field | 4-5 files | 1 YAML file |
| Risk of inconsistencies | ✓ | ✕ |
| Automatic TCA generation | ✕ | ✓ |
| Automatic SQL generation | ✕ | ✓ |
| Maintenance effort | High | Minimal |
Why a Single Source of Truth is Essential in the Era of AI Agents
As AI-assisted coding agents increasingly analyse, extend, and refactor code, the structure of the codebase decides whether they succeed. Studies show that 65% of developers run into a lack of context when refactoring, a problem that fragmented code only makes worse.
For AI Agents
A single central YAML definition lets tools like Cursor or Claude grasp the entire data structure in one pass. No jumping between TCA, SQL, and Model files; the agent immediately understands what is defined.
For Developers
Developer Experience (DX) covers the full range of interactions with tools, processes, and code. According to Gartner, teams with high DX hit their business goals 33% more often and see 20% lower turnover.
"AI agents rely on the context provided by the codebase to generate relevant code. A poorly organized codebase can lead to 'context rot,' where the agent misses dependencies and produces suboptimal code."
The DRY principle and Single Source of Truth are no longer abstract best practices; they are the precondition for AI agents to extend your codebase productively.
Code Example: Team Member as a Content Element
Defining a Content Element for team members takes just one YAML file:
You describe what you need, not how TYPO3 should process it internally. This makes extensions cleaner, more portable, and future-proof.
Record Types: Defining Custom Records
The Content Blocks extension is not limited to Content Elements in tt_content. With Record Types, you create your own database tables, ideal for news, products, events, or other structured data.
For existing extensions, we offer a Migration Skill for AI coding agents like Cursor or Claude Code. The skill provides bidirectional instructions: from classic TCA/SQL to Content Blocks, and back again if needed. Status: Alpha — feedback welcome.
Content Elements vs. Record Types
| Feature | Content Elements | Record Types |
|---|---|---|
| Table | tt_content | New or existing table |
| Rendering | Directly on the page | Via plugin or custom template |
| Placement | In page content | In folders (SysFolders) |
| Use case | Visual page components | Structured data records |
| Examples | Hero, Accordion, Tabs, CTA | News, Products, Events, Locations |
| Folder | ContentBlocks/ContentElements/ | ContentBlocks/RecordTypes/ |
With typeName, you add custom types to existing tables, for example a custom news type for tx_news_domain_model_news.
Extbase-Compatible Table Naming
Important: for seamless integration with Extbase repositories, follow the naming convention tx_extensionkey_domain_model_*. Only then will model generators and repositories work correctly.
Example: News Article as a Record Type
A complete news system in one YAML file:
The classic approach would need ~150 lines of TCA, ~20 lines of SQL, and separate Model and Repository classes for this. With Content Blocks: one YAML file.
Page Types: Defining Custom Page Types
Page Types extend the pages table with custom page types, ideal for blog articles, landing pages, news pages, or other page types with special properties.
When to Use Page Types
Structured Page Properties
When pages require fixed fields (author, teaser image, publication date) that appear on every page of this type.
Plugin Integration
Plugins can read Page Types – ideal for news lists, blog archives, or event calendars.
Example: Blog Article as a Page Type
Use the current Unix timestamp as typeName; the make:content-block CLI command generates this automatically. Reserved values: 199, 254.
Integrating the Frontend Template
Page Types do not provide automatic frontend rendering. Add the ContentBlocksDataProcessor to your TypoScript:
All fields are then available in the template as {data.author_name}, {data.hero_image}, and so on.
File Types: Extended File Metadata
Since Content Blocks v1.2File Types extend the sys_file_reference table with custom fields, perfect for photographer credits, copyright notices, or additional image options.
Available File Types
| typeName | File Types |
|---|---|
image | JPEG, PNG, GIF, WebP, SVG |
video | MP4, WebM, OGG |
audio | MP3, WAV, OGG |
text | TXT, PDF, Markdown |
application | ZIP, Office formats |
Example: Extended Image Metadata
Particularly useful for agencies and companies with strict image-rights requirements: copyright and source information are stored directly with the file.
PHP 8.4: Property Hooks Replace Getters & Setters
A large share of every classic Extbase model is taken up by repetitive getter and setter methods. PHP 8.4 Property Hooks change that fundamentally.
The Paradigm Shift
Concrete Advantages of Property Hooks
| Aspect | PHP 8.3 | PHP 8.4 |
|---|---|---|
| Lines of code (example above) | ~35 lines | ~25 lines |
| Logic location | In separate methods | Directly on the property |
| Virtual Properties | Only via getters | Native support |
| Learning curve | Familiar pattern | New concept |
Property Hooks are a PHP 8.4 feature. Projects on PHP 8.3 or older still need classic getters and setters, so plan your upgrade accordingly.
What Property Hooks Enable
The Synergy: Content Blocks + Property Hooks
Combining the two technologies gives you a clean division of labour:
Instead of 300 lines of boilerplate: 40 lines of YAML + optional business logic
The Result:
- YAML defines the data structure (Single Point of Truth)
- PHP Models now only contain business logic (Property Hooks)
- No more boilerplate for TCA, SQL, or trivial getters/setters
butu demonstrates this impressively in the wp_cbexample extension: 4 complete Domain Models with just a single manual TCA file (for plugin registration). A new property touches only 2 files: config.yaml and Model.php.
Overview of Additional CLI Commands
Alongside make:content-block, Content Blocks ships several other handy commands:
| Command | Function |
|---|---|
| content-blocks:list | Lists all registered Content Blocks |
| content-blocks:language:generate | Generates language files for all fields |
| content-blocks:assets:publish | Publishes assets (CSS/JS) to the public folder |
Internationalisation (i18n)
Content Blocks makes multilingual sites far simpler. You manage labels and translations centrally in a labels.xlf file inside the Content Block folder.
Folder Structure
Using Labels in Templates
Making Record Types Multilingual
For Record Types, activate languageAware in the config.yaml:
vendor/bin/typo3 content-blocks:language:generate generates labels.xlf automatically for all defined fields.
Tooling and Resources
Example Extension by butu
butu's wp_cbexample extension shows impressively how Content Blocks and PHP 8.4 Property Hooks work together in practice: 4 Models, only 1 manual TCA file. An excellent proof of concept for modern TYPO3 development.
Agent Skills
The Content Blocks Skill for Cursor and Claude Code contains detailed prompts and examples for Content Elements, Record Types, and migrations.
wp_make Extension
The wp_make extension generates Extbase Models and Repositories to match your Content Blocks Record Types.
Official Documentation
The TYPO3 Content Blocks Documentation offers the complete YAML reference and API description.
Conclusion: Act Now, Profit Later
Immediately Applicable
Content Blocks already work with current TYPO3 versions. Start every new extension with the declarative approach from day one.
Future-Proof
We recommend this approach: PHP 8.4 Property Hooks combined with Content Blocks already deliver substantial benefits, and a possible core integration in TYPO3 v15 LTS would protect the investment even further.
The combination of TYPO3 Content Blocks and PHP 8.4 Property Hooks does more than cut the initial development effort; it makes your extensions far more maintainable in the long run.