Anyone developing TYPO3 extensions knows the scenario: A new database field means changes in five different places – ext_tables.sql, TCA configuration, Domain Model, Repository, and Fluid template. This costs time, causes inconsistencies, and makes maintenance a test of patience.
The good news: Two modern approaches eliminate this overhead: Content Blocks for declarative data structures and PHP 8.4 Property Hooks for lean Domain Models. Together, they reduce boilerplate by up to 80%.
Terminology
Before we begin, a brief 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_metadata) |
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 are the benefits of switching to Content Blocks?
Effort: Classic vs. Content Blocks + PHP 8.4
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 is reduced from ~300 lines of boilerplate to ~40 lines of declarative YAML definition. Maintenance becomes predictable, and sources of error drop dramatically.
Installing Content Blocks
Install in just a few steps – depending on your setup, via Composer or the Extension Manager.
In Classic Mode, it is essential to block access to the ContentBlocks folder via the web server. Otherwise, internal configuration files will be publicly accessible.
Creating New Content Types via CLI
The make:content-block command – inspired by the proven EXT:make extension – generates the complete basic structure for a new Content Block in seconds.
Interactive Mode
Direct Call 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 define your own templates. Ideal for teams wanting 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 multiple files:
Traditional: One field, five adjustments
Every change requires manual synchronisation. If you forget one place, discrepancies between the database schema and backend form threaten – 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 this, 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 – without 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
In an era where AI-supported coding agents increasingly analyse, extend, and refactor code, the structure of the codebase determines success. Studies show: 65% of developers experience a lack of context during refactoring – a problem that is amplified by fragmented code.
For AI Agents
A central YAML definition allows tools like Cursor or Claude to grasp the entire data structure in a single pass. No jumping between TCA, SQL, and Model files – the agent immediately understands what is defined.
For Developers
Developer Experience (DX) describes the totality of all interactions with tools, processes, and code. According to Gartner, teams with high DX achieve their business goals 33% more frequently and show 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 prerequisite for AI agents to productively extend your codebase.
Code Example: Team Member as a Content Element
Define a Content Element for team members – one YAML file is enough:
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 contains bidirectional instructions: from classic TCA/SQL to Content Blocks – and back again if necessary. 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 – e.g., a custom news type for tx_news_domain_model_news.
Extbase-Compatible Table Naming
Important: For seamless integration with Extbase repositories, use the naming convention tx_extensionkey_domain_model_*. Only then will model generators and repositories function correctly.
Example: News Article as a Record Type
A complete news system in one YAML file:
Classically, you 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 CLI command make:content-block generates this automatically. Reserved values: 199, 254.
Integrating the Frontend Template
Page Types do not offer automatic frontend rendering. Add the ContentBlocksDataProcessor to your TypoScript:
Afterwards, all fields are available in the template under {data.author_name}, {data.hero_image}, etc.
File Types: Extended File Metadata
Since Content Blocks v1.2File Types extend the sys_file_metadata table with custom fields – perfect for photographers, 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 significant portion of classic Extbase models consists of repetitive getter and setter methods. PHP 8.4 Property Hooks change this 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 require classic getters/setters. Plan your upgrade accordingly.
What Property Hooks Enable
The Synergy: Content Blocks + Property Hooks
The combination of both technologies leads to a clear division of tasks:
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 impressively demonstrates in his wp_cbexample extension: 4 complete Domain Models with just a single manual TCA file (for plugin registration). New properties require changes to only 2 files: config.yaml and Model.php.
Overview of Additional CLI Commands
In addition to make:content-block, Content Blocks offers other useful 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 significantly simplifies multilingualism. You manage labels and translations centrally in a labels.xlf file within the Content Block folder.
Folder Structure
Using Labels in Templates
Making Record Types Multilingual
For Record Types, activate languageAware in the config.yaml:
With vendor/bin/typo3 content-blocks:language:generate, you automatically generate labels.xlf for all defined fields.
Tooling and Resources
Example Extension by butu
The wp_cbexample extension by butu impressively shows how Content Blocks and PHP 8.4 Property Hooks interact 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 matching 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 new extensions directly with the declarative approach.
Future-Proof
We recommend this approach: PHP 8.4 Property Hooks combined with Content Blocks already offer substantial benefits – and a potential core integration in TYPO3 v14 would further secure this investment.
The combination of TYPO3 Content Blocks and PHP 8.4 Property Hooks not only reduces the initial development effort – it makes your extensions significantly more maintainable.