--- name: typo3-content-blocks description: Create, edit, and troubleshoot TYPO3 Content Blocks from the friendsoftypo3/content-blocks extension. Use this skill whenever the user asks for TYPO3 Content Blocks, content block `config.yaml`, `ContentBlocks/ContentElements`, `ContentBlocks/PageTypes`, `ContentBlocks/RecordTypes`, Content Block fields, templates, backend previews, icons, generated fields, the `make:content-block` command, `content-blocks:lint`, schema validation errors, missing CType/page/record types, broken labels, Content Block rendering/debugging, or integrating Content Blocks with EXT:container (b13/container) for nested grid containers. license: CC-BY-4.0 compatibility: Requires a TYPO3 project with friendsoftypo3/content-blocks installed; the project CLI is used for generation and validation when available. --- # TYPO3 Content Blocks Use this skill for TYPO3 projects using `friendsoftypo3/content-blocks`. The extension defines content types with a component-like folder containing `config.yaml`, optional assets, templates, and labels. ## First Checks 1. Locate the loaded site package or extension that should own the Content Block. 2. Check whether `friendsoftypo3/content-blocks` is installed and whether the project uses Composer mode. 3. Find existing Content Blocks before adding new conventions: - `ContentBlocks/ContentElements/*/config.yaml` - `ContentBlocks/PageTypes/*/config.yaml` - `ContentBlocks/RecordTypes/*/config.yaml` - `ContentBlocks/FileTypes/*/config.yaml` - `ContentBlocks/Basics/*.yaml` 4. Read the nearest existing Content Block and follow its naming, labels, groups, templates, and asset style. 5. If the exact field syntax is uncertain, consult the official docs or local schemas before editing. ## Core Layout A Content Block is auto-discovered when a loaded extension contains a folder below the correct `ContentBlocks` type directory and that folder contains `config.yaml`. Use these canonical locations: ```text EXT:site_package/ContentBlocks/ContentElements/my-element/config.yaml EXT:site_package/ContentBlocks/PageTypes/my-page-type/config.yaml EXT:site_package/ContentBlocks/RecordTypes/my-record-type/config.yaml EXT:site_package/ContentBlocks/FileTypes/my-file-type/config.yaml EXT:site_package/ContentBlocks/Basics/shared-fields.yaml ``` Optional resources live next to `config.yaml`: ```text assets/icon.svg assets/frontend.css assets/frontend.js language/labels.xlf templates/frontend.html # or frontend.fluid.html (MUST be strictly lowercase) templates/backend-preview.html # or backend-preview.fluid.html (MUST be strictly lowercase) templates/partials/* templates/layouts/* ``` > [!CRITICAL] > **Template Naming & Case Sensitivity:** > Content Blocks strictly expects lowercase filenames: `frontend.html` / `frontend.fluid.html` and `backend-preview.html` / `backend-preview.fluid.html`. > Unlike classic TYPO3 Fluid elements which often use PascalCase (e.g. `Frontend.html`), Content Blocks checks for lowercase template names on disk via `file_exists()`. On case-sensitive Linux/Docker hosts (such as DDEV), a capitalized filename like `Frontend.html` will fail this check silently. As a result, the TypoScript generator skips registering `tt_content. =< lib.contentBlock`, producing: > `ERROR: Content Element with uid "X" and type "..." has no rendering definition!`. ## Creation Workflow Prefer the project-local generator when available because it creates the expected folder, label file, templates, and icon skeleton: ```bash vendor/bin/typo3 make:content-block --content-type="content-element" --vendor="vendor-name" --name="my-element" --title="My Element" --extension="site_package" ``` Use `content-element`, `page-type`, or `record-type` for `--content-type`. Page types require an integer `--type-name`. After creating or changing fields, run the project equivalent of: ```bash vendor/bin/typo3 cache:flush -g system vendor/bin/typo3 extension:setup --extension=site_package vendor/bin/typo3 content-blocks:lint ``` If the project has wrappers such as `ddev`, `composer`, `bin/typo3`, `Build/Scripts`, or Makefile targets, use those instead of hard-coding the bare command. ## Editing Workflow 1. Parse `config.yaml` as YAML. Avoid regex edits for structured changes. 2. Preserve existing root options such as `name`, `group`, `basics`, `prefixFields`, `prefixType`, `typeName`, `labelField`, and `fallbackLabelFields`. 3. Reuse existing TYPO3 fields only with `useExistingField: true`, commonly for fields such as `header` or `bodytext`; do not reuse system fields casually. 4. Add new fields with unique `identifier` values within the Content Block. 5. Add or update `language/labels.xlf` for editor-visible labels and descriptions. 6. Update both `templates/frontend.fluid.html` and `templates/backend-preview.fluid.html` when the editor preview needs to mirror frontend content. 7. If adding assets, reference them with Content Block ViewHelpers in Fluid rather than assuming a public path. 8. Re-run linting and the project cache/database update path after schema or field changes. ## Troubleshooting Workflow Start with the observable symptom, then narrow the layer: - **Block not listed:** verify folder path, loaded extension, `config.yaml` filename, valid `name`, extension dependency on Content Blocks, and backend user group permissions for generated CType/fields. - **Schema or YAML error:** run `vendor/bin/typo3 content-blocks:lint`; use the reported JSON pointer path to find the invalid field or root option. - **Fields missing in backend:** flush system cache, run extension setup/database compare, confirm field identifiers and prefixing, and check backend user permissions. - **Frontend value missing:** use `{data.fieldIdentifier}` for processed properties and `{data.rawRecord.field_name}` for raw database values. - **Relations not rendering:** remember that `Collection`, `Select`, `Relation`, `File`, `Folder`, `Category`, and `FlexForm` fields are resolved automatically in Content Block templates. - **Assets missing:** check `assets/`, published assets, and `cb:assetPath()` usage in Fluid. - **Labels show identifiers:** add/update `language/labels.xlf`; for places where Content Blocks cannot centralize labels, use a TCA override for a default column label. - **No rendering definition error (`ERROR: Content Element with uid "..." and type "..." has no rendering definition!`):** check the template filename case! The template file MUST be lowercase `templates/frontend.html` (or `frontend.fluid.html`). On case-sensitive environments (Linux/Docker/DDEV), a PascalCase file like `Frontend.html` fails `TypoScriptGenerator`'s internal `file_exists()` check, silently omitting `tt_content. =< lib.contentBlock`. Rename the file to lowercase and flush the system cache (`ddev typo3 cache:flush -g system`). - **Database row too large:** reduce generated columns, use relations/collections where appropriate, or revisit field prefixing and duplicated basics. ## Fluid Notes Inside `frontend.fluid.html` and `backend-preview.fluid.html`, use the Content Blocks data object: ```html {data.header} {data.my_text_field} {data.rawRecord.vendor_field_name} {item.title} ``` Use Content Block ViewHelpers for local assets and labels: ```html ``` ## Container Integration (EXT:container / b13/container) Content Blocks and EXT:container complement each other: Content Blocks owns the element definition, icon registration, and Fluid templates; EXT:container owns the grid configuration and backend column rendering. ### Step 1 — Define the Content Block Create a Content Block with `group: container` and `saveAndClose: true`. Do not add Collection fields for the child columns; the column layout is handled by EXT:container. ```yaml name: vendor/two-column-container typeName: vendor_two_columns_container group: container saveAndClose: true fields: - identifier: header useExistingField: true ``` ### Step 2 — Register the Container Grid via TCA Override Register the column grid directly on `$GLOBALS['TCA']`, **not** via `Registry::configureContainer()`. Content Blocks reads this TCA key to wire the backend preview. File: `EXT:site_package/Configuration/TCA/Overrides/tt_content.php` ```php 'Left', 'colPos' => 200], ['name' => 'Right', 'colPos' => 201], ], ] ); $GLOBALS['TCA']['tt_content']['containerConfiguration'][$containerConfiguration->getCType()] = $containerConfiguration->toArray(); ``` > **Note:** As of EXT:container 4.0.0 you no longer need to manually override the preview renderer — Content Blocks handles that automatically. ### Step 3 — Add the TypoScript Rendering Definition Extend the Content Block's TypoScript object with a `ContainerProcessor` for each column: ```typoscript tt_content.vendor_two_columns_container { dataProcessing { 100 = B13\Container\DataProcessing\ContainerProcessor 100 { colPos = 200 as = children_left } 110 = B13\Container\DataProcessing\ContainerProcessor 110 { colPos = 201 as = children_right } } } ``` Alternatively, use the parameter-free form to get auto-named variables `children_`: ```typoscript tt_content.vendor_two_columns_container { dataProcessing { 100 = B13\Container\DataProcessing\ContainerProcessor } } ``` ### Step 4 — Render Children in the Fluid Template In `templates/frontend.fluid.html`, iterate the processor-populated variables: ```html
{child.renderedContent}
{child.renderedContent}
``` #### TYPO3 v14 — ContentAreaProcessor alternative For TYPO3 v14+ with EXT:container 4.0+, you can use `ContentAreaProcessor` instead. It lazily loads container columns into a `content` variable and enables rendering with the `f:render.contentArea()` and `f:render.record()` ViewHelpers: ```typoscript tt_content.vendor_two_columns_container { dataProcessing { 100 = B13\Container\DataProcessing\ContentAreaProcessor } } ``` ```html
{content.200 -> f:render.contentArea()}
{record -> f:render.record()}
``` ### Key Differences vs. Pure b13/container Approach | Concern | Pure b13/container | Content Blocks + b13/container | |---|---|---| | CType registration | `Registry::configureContainer()` | Content Block `config.yaml` (auto-registered) | | Label/description | In `configureContainer()` args | `language/labels.xlf` | | TCA column grid | Also via `Registry::configureContainer()` | Direct `$GLOBALS['TCA']['tt_content']['containerConfiguration']` | | Frontend template | Site TypoScript + custom Fluid paths | Content Block `templates/frontend.fluid.html` | | Icon | `->setIcon()` on config | `assets/icon.svg` in Content Block | | Preview renderer override | Required for older versions | Not needed for EXT:container ≥ 4.0.0 | ## References Read [references/content-blocks-patterns.md](references/content-blocks-patterns.md) when you need concrete examples, docs links, validation details, or a troubleshooting checklist. ## Safety And Completion Do not run generators or schema/database updates until the target site package and block type are known. Preserve existing generated fields and labels unless the request explicitly changes them. Complete the task only after YAML parses, `content-blocks:lint` passes through the project's normal command wrapper, and the block is visible and renders in the intended backend and frontend context.