重要前提
安装AI Skills的关键前提是:必须科学上网,且开启TUN模式,这一点至关重要,直接决定安装能否顺利完成,在此郑重提醒三遍:科学上网,科学上网,科学上网。查看完整安装教程 →
typo3-content-blocks by dirnbauer/webconsulting-skills
npx skills add https://github.com/dirnbauer/webconsulting-skills --skill typo3-content-blocks兼容性说明: 此技能针对 TYPO3 v14.x 和 Content Blocks 2.x。请始终将 Packagist
friendsoftypo3/content-blocks的版本约束与您的 Core 版本匹配。对于 TYPO3 v13 上的 Content Blocks 1.x,上游要求 TYPO3 ≥ 13.4 (typo3/cms-core: ^13.4) —— 请在 Packagist 上确认。示例使用 TYPO3 v14 API 和 CB 2.x;如果上游约束不同,请调整composer.json。
TYPO3 API 优先: 在创建自定义实现之前,始终优先使用 TYPO3 的内置 API、核心功能和既定约定。不要重复发明 TYPO3 已经提供的东西。始终通过查阅官方 TYPO3 文档来验证您使用的 API 和方法在 TYPO3 v14 中存在且未被弃用。
Content Blocks 是在 TYPO3 中创建自定义内容类型的现代方法。它通过提供单一的 YAML 配置来生成以下内容,从而消除了冗余:
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
| 传统方法 | Content Blocks 方法 |
|---|---|
| 多个 TCA 文件 | 一个 config.yaml |
| 手动 SQL 定义 | 自动生成的模式 |
| 单独的 TypoScript | 自动注册的渲染 |
| 分散的翻译 | 单一的 labels.xlf |
| 复杂的设置 | 简单的文件夹结构 |
# 通过 Composer 安装(推荐使用 DDEV)
ddev composer require friendsoftypo3/content-blocks
# 安装后,清除缓存
ddev typo3 cache:flush
版本约束: Content Blocks 1.x 要求 TYPO3 ≥ 13.4(包中的
typo3/cms-core: ^13.4)。TYPO3 13.1–13.3 不满足该 Composer 约束。
对于非 Composer 安装,拒绝 Web 访问 ContentBlocks 文件夹:
# .htaccess 添加项
RewriteRule (?:typo3conf/ext|typo3/sysext|typo3/ext)/[^/]+/(?:Configuration|ContentBlocks|Resources/Private|Tests?|Documentation|docs?)/ - [F]
Content Blocks 支持四种内容类型:
| 类型 | 文件夹 | 表 | 使用场景 |
|---|---|---|---|
ContentElements | ContentBlocks/ContentElements/ | tt_content | 前端内容(英雄区域、手风琴、行动号召) |
RecordTypes | ContentBlocks/RecordTypes/ | 自定义/现有表 | 结构化记录(新闻、产品、团队) |
PageTypes | ContentBlocks/PageTypes/ | pages | 自定义页面类型(博客、落地页) |
FileTypes | ContentBlocks/FileTypes/ | sys_file_reference | 扩展的文件引用(摄影师、版权) |
EXT:my_sitepackage/
└── ContentBlocks/
├── ContentElements/
│ └── my-hero/
│ ├── assets/
│ │ └── icon.svg
│ ├── language/
│ │ └── labels.xlf
│ ├── templates/
│ │ ├── backend-preview.fluid.html
│ │ ├── frontend.fluid.html
│ │ └── partials/
│ └── config.yaml
├── RecordTypes/
│ └── my-record/
│ ├── assets/
│ │ └── icon.svg
│ ├── language/
│ │ └── labels.xlf
│ └── config.yaml
├── PageTypes/
│ └── blog-article/
│ ├── assets/
│ │ ├── icon.svg
│ │ ├── icon-hide-in-menu.svg
│ │ └── icon-root.svg
│ ├── language/
│ │ └── labels.xlf
│ ├── templates/
│ │ └── backend-preview.fluid.html
│ └── config.yaml
└── FileTypes/
└── image-extended/
├── language/
│ └── labels.xlf
└── config.yaml
# 交互模式
ddev typo3 make:content-block
# 单行命令
ddev typo3 make:content-block \
--content-type="content-element" \
--vendor="myvendor" \
--name="hero-banner" \
--title="Hero Banner" \
--extension="my_sitepackage"
# 创建后,更新数据库
ddev typo3 cache:flush -g system
ddev typo3 extension:setup --extension=my_sitepackage
在 basics: 下列出以引入核心字段组:TYPO3/Header、TYPO3/Appearance、TYPO3/Links、TYPO3/Categories。请参阅 Content Blocks 基础字段参考。
# EXT:my_sitepackage/ContentBlocks/ContentElements/hero-banner/config.yaml
name: myvendor/hero-banner
fields:
- identifier: header
useExistingField: true
- identifier: bodytext
useExistingField: true
# EXT:my_sitepackage/ContentBlocks/ContentElements/hero-banner/config.yaml
name: myvendor/hero-banner
group: default
description: "带有图片和行动号召的全宽英雄横幅"
prefixFields: true
prefixType: full
basics:
- TYPO3/Appearance
- TYPO3/Links
fields:
- identifier: header
useExistingField: true
- identifier: subheadline
type: Text
label: 副标题
- identifier: hero_image
type: File
minitems: 1
maxitems: 1
allowed: common-image-types
- identifier: cta_link
type: Link
label: 行动号召链接
- identifier: cta_text
type: Text
label: 按钮文本
<!-- templates/frontend.fluid.html -->
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
xmlns:cb="http://typo3.org/ns/TYPO3/CMS/ContentBlocks/ViewHelpers"
data-namespace-typo3-fluid="true">
<f:asset.css identifier="hero-banner-css" href="{cb:assetPath()}/frontend.css"/>
<section class="hero-banner">
<f:if condition="{data.hero_image}">
<f:for each="{data.hero_image}" as="image">
<f:image image="{image}" alt="{data.header}" class="hero-image"/>
</f:for>
</f:if>
<div class="hero-content">
<h1>{data.header}</h1>
<f:if condition="{data.subheadline}">
<p class="subheadline">{data.subheadline}</p>
</f:if>
<f:if condition="{data.cta_link}">
<f:link.typolink parameter="{data.cta_link}" class="btn btn-primary">
{data.cta_text -> f:or(default: '了解更多')}
</f:link.typolink>
</f:if>
</div>
</section>
</html>
<!-- templates/backend-preview.fluid.html -->
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
xmlns:be="http://typo3.org/ns/TYPO3/CMS/Backend/ViewHelpers"
data-namespace-typo3-fluid="true">
<div class="content-block-preview">
<strong>{data.header}</strong>
<f:if condition="{data.subheadline}">
<br/><em>{data.subheadline}</em>
</f:if>
<f:if condition="{data.hero_image}">
<f:for each="{data.hero_image}" as="image">
<be:thumbnail image="{image}" width="100" height="100"/>
</f:for>
</f:if>
</div>
</html>
记录类型为结构化数据(如团队、产品、事件等)创建自定义数据库表。
重要: 为了兼容 Extbase,请使用 tx_extensionkey_domain_model_* 命名约定:
# ✅ 正确 - 兼容 Extbase 的表名
name: myvendor/team-member
table: tx_mysitepackage_domain_model_teammember
labelField: name
fields:
- identifier: name
type: Text
- identifier: position
type: Text
- identifier: email
type: Email
- identifier: photo
type: File
allowed: common-image-types
maxitems: 1
# ❌ 错误 - 短表名不适用于 Extbase
name: myvendor/team-member
table: team_member # 无法与 Extbase 配合使用!
# EXT:my_sitepackage/ContentBlocks/RecordTypes/team-member/config.yaml
name: myvendor/team-member
table: tx_mysitepackage_domain_model_teammember
labelField: name
fields:
- identifier: name
type: Text
# EXT:my_sitepackage/ContentBlocks/RecordTypes/team-member/config.yaml
name: myvendor/team-member
table: tx_mysitepackage_domain_model_teammember
labelField: name
fallbackLabelFields:
- email
languageAware: true
workspaceAware: true
sortable: true
softDelete: true
trackCreationDate: true
trackUpdateDate: true
internalDescription: true
restriction:
disabled: true
startTime: true
endTime: true
userGroup: true # 适用时的 fe_group 可见性字段
security:
ignorePageTypeRestriction: true # 允许在普通页面上使用
fields:
- identifier: name
type: Text
required: true
- identifier: position
type: Text
- identifier: email
type: Email
- identifier: phone
type: Text
- identifier: bio
type: Textarea
enableRichtext: true
- identifier: photo
type: File
allowed: common-image-types
maxitems: 1
- identifier: social_links
type: Collection
labelField: platform
fields:
- identifier: platform
type: Select
renderType: selectSingle
items:
- label: LinkedIn
value: linkedin
- label: Twitter/X
value: twitter
- label: GitHub
value: github
- identifier: url
type: Link
Content Blocks 为记录类型公开了许多可选的根键 —— 请始终根据当前的记录类型 YAML 参考确认名称。常用的标志包括:
| 选项 | 作用 |
|---|---|
editLocking | 编辑锁定行为 |
sortField / sortable | 手动排序(sorting 列) |
rootLevelType | 允许在 PID 0 处创建记录 |
readOnly | 在 FormEngine 中只读 |
adminOnly | 仅对管理员可见 |
hideAtCopy / appendLabelAtCopy | 复制行为 |
group | 后端选择器分组 |
为一个表创建多种类型:
# EXT:my_sitepackage/ContentBlocks/RecordTypes/person-employee/config.yaml
name: myvendor/person-employee
table: tx_mysitepackage_domain_model_person
typeField: person_type
typeName: employee
priority: 0 # 整数排序;值越大加载越早(优先级越高)
labelField: name
languageAware: false
workspaceAware: false
fields:
- identifier: name
type: Text
- identifier: department
type: Text
# EXT:my_sitepackage/ContentBlocks/RecordTypes/person-contractor/config.yaml
name: myvendor/person-contractor
table: tx_mysitepackage_domain_model_person
typeName: contractor
fields:
- identifier: name
type: Text
- identifier: company
type: Text
- identifier: contract_end
type: DateTime
定义一个可在 IRRE 集合中使用的记录:
# EXT:my_sitepackage/ContentBlocks/RecordTypes/slide/config.yaml
name: myvendor/slide
table: tx_mysitepackage_domain_model_slide
labelField: title
fields:
- identifier: title
type: Text
- identifier: image
type: File
maxitems: 1
- identifier: link
type: Link
# EXT:my_sitepackage/ContentBlocks/ContentElements/slider/config.yaml
name: myvendor/slider
fields:
- identifier: slides
type: Collection
foreign_table: tx_mysitepackage_domain_model_slide
shareAcrossTables: true
shareAcrossFields: true
minitems: 1
页面类型使用自定义页面类型扩展 pages 表 —— 非常适合博客文章、落地页、新闻页面或其他具有特殊属性的页面变体。
| 使用场景 | 示例 |
|---|---|
| 结构化页面属性 | 带有作者、摘要图片、发布日期等的博客 |
| 插件集成 | 新闻列表、事件日历读取页面属性 |
| 不同的页面行为 | 无导航的落地页 |
| SEO 特定字段 | 每种页面类型的自定义元字段 |
# EXT:my_sitepackage/ContentBlocks/PageTypes/blog-article/config.yaml
name: myvendor/blog-article
typeName: 1705234567
fields:
- identifier: author_name
type: Text
# EXT:my_sitepackage/ContentBlocks/PageTypes/blog-article/config.yaml
name: myvendor/blog-article
typeName: 1705234567 # Unix 时间戳(唯一标识符)
group: default # 选项:default, link, special
fields:
- identifier: author_name
type: Text
label: 作者
required: true
- identifier: teaser_text
type: Textarea
label: 摘要
- identifier: hero_image
type: File
allowed: common-image-types
maxitems: 1
- identifier: publish_date
type: DateTime
label: 发布日期
- identifier: reading_time
type: Number
label: 阅读时间(分钟)
| 选项 | 类型 | 必需 | 描述 |
|---|---|---|---|
typeName | integer | ✓ | 唯一的 doktype 编号(使用 Unix 时间戳) |
group | string | 选择器中的分组:default、link、special | |
allowedRecordTypes | array | 允许在此 doktype 上使用的记录类型(默认包括 pages、sys_category、sys_file_reference、sys_file_collection;可使用 * 通配符 —— 参见官方页面类型 API) |
保留的 typeName 值: 199, 254(不能使用)
页面类型支持特定状态的图标。将这些图标添加到您的资源文件夹:
ContentBlocks/PageTypes/blog-article/
├── assets/
│ ├── icon.svg # 默认图标
│ ├── icon-hide-in-menu.svg # 菜单中隐藏状态
│ └── icon-root.svg # 站点根状态
└── config.yaml
创建一个 backend-preview.fluid.html 来预览自定义页面属性:
<!-- templates/backend-preview.fluid.html -->
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
xmlns:be="http://typo3.org/ns/TYPO3/CMS/Backend/ViewHelpers"
data-namespace-typo3-fluid="true">
<div class="card card-size-medium">
<div class="card-body">
<be:link.editRecord uid="{data.uid}" table="{data.mainType}" fields="author_name">
<strong>作者:</strong> {data.author_name}
</be:link.editRecord>
<f:if condition="{data.publish_date}">
<br/><small>发布日期:<f:format.date format="d.m.Y">{data.publish_date}</f:format.date></small>
</f:if>
</div>
</div>
</html>
页面类型没有自动的前端渲染。将 ContentBlocksDataProcessor 添加到您的 TypoScript 中:
# Configuration/TypoScript/setup.typoscript
page = PAGE
page {
10 = FLUIDTEMPLATE
10 {
templateName = Default
templateRootPaths.10 = EXT:my_sitepackage/Resources/Private/Templates/
dataProcessing {
# 处理 Content Blocks 页面数据
1 = content-blocks
}
}
}
然后在您的 Fluid 模板中访问字段:
<!-- Resources/Private/Templates/Default.html -->
<f:if condition="{data.author_name}">
<p class="author">作者:{data.author_name}</p>
</f:if>
<f:if condition="{data.hero_image}">
<f:for each="{data.hero_image}" as="image">
<f:image image="{image}" class="hero-image"/>
</f:for>
</f:if>
要将您的页面类型从“创建新页面”拖放区域隐藏:
# Configuration/user.tsconfig
options {
pageTree {
doktypesToShowInNewPageDragArea := removeFromList(1705234567)
}
}
版本 1.2 新增功能
文件类型使用自定义字段扩展 sys_file_reference 表 —— 非常适合摄影师署名、版权声明或其他引用级别的附加选项。
| typeName | 文件类型 |
|---|---|
image | JPEG、PNG、GIF、WebP、SVG |
video | MP4、WebM、OGG |
audio | MP3、WAV、OGG |
text | TXT、PDF、Markdown |
application | ZIP、Office 格式 |
# EXT:my_sitepackage/ContentBlocks/FileTypes/image-extended/config.yaml
name: myvendor/image-extended
typeName: image
fields:
- identifier: photographer
type: Text
label: 摄影师
# EXT:my_sitepackage/ContentBlocks/FileTypes/image-extended/config.yaml
name: myvendor/image-extended
typeName: image
prefixFields: false # 保持原始列名
fields:
- identifier: image_overlay_palette
type: Palette
label: 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette'
fields:
# 重用现有的 TYPO3 核心字段
- identifier: alternative
useExistingField: true
- identifier: description
useExistingField: true
- type: Linebreak
- identifier: link
useExistingField: true
- identifier: title
useExistingField: true
- type: Linebreak
# 自定义字段
- identifier: photographer
type: Text
label: 摄影师
- identifier: copyright
type: Text
label: 版权声明
- identifier: source_url
type: Link
label: 来源 URL
- type: Linebreak
- identifier: crop
useExistingField: true
| 选项 | 类型 | 必需 | 描述 |
|---|---|---|---|
typeName | string | ✓ | 其中之一:text、image、audio、video、application |
prefixFields | boolean | 是否用内容块名称前缀化字段标识符(对于文件类型,通常为 false 以保持共享的字段名) |
| 使用场景 | 可添加的字段 |
|---|---|
| 摄影机构 | photographer、copyright、license_type、expiry_date |
| 视频平台 | director、duration、transcript、subtitles |
| 文档管理 | document_version、author、confidentiality |
| 电子商务 | product_sku、variant_color、variant_size |
在 Fluid 模板中,通过 FAL 引用访问自定义元数据:
<f:for each="{data.images}" as="image">
<figure>
<f:image image="{image}" alt="{image.alternative}"/>
<f:if condition="{image.properties.photographer}">
<figcaption>
照片:{image.properties.photographer}
<f:if condition="{image.properties.copyright}">
| © {image.properties.copyright}
</f:if>
</figcaption>
</f:if>
</figure>
</f:for>
| 类型 | 描述 | 示例 |
|---|---|---|
Text | 单行文本 | type: Text |
Textarea | 多行文本 | type: Textarea |
Email | 电子邮件地址 | type: Email |
Link | 链接/URL | type: Link |
Number | 整数/浮点数 | type: Number(+ format: integer 或 format: decimal 根据需要;旧版 YAML 有时使用不存在的 Integer 类型 —— 请使用 Number) |
DateTime | 日期和/或时间 | type: DateTime |
Color | 颜色选择器 | type: Color |
Checkbox | 布尔复选框 | type: Checkbox |
Radio | 单选按钮 | type: Radio |
Slug | URL 别名 | type: Slug |
Password | 密码字段 | type: Password |
Basic | 共享的“基础”字段辅助器 | type: Basic |
Country | 国家选择(与 TCA country 对齐,在支持的情况下) | type: Country |
Pass | 虚拟字段,在后端不可见;用于存储由扩展逻辑处理的数据 | type: Pass |
SelectNumber | 带有数值的选择 | type: SelectNumber |
Uuid | UUID 字符串 | type: Uuid |
| 类型 | 描述 | 示例 |
|---|---|---|
File | 文件引用(FAL) | type: File |
Relation | 记录关系 | type: Relation |
Select | 下拉选择 | type: Select |
Category | 系统分类 | type: Category |
Collection | 内联记录(IRRE) | type: Collection |
Folder | 文件夹引用 | type: Folder |
Language | 语言选择器 | type: Language |
| 类型 | 描述 | 示例 |
|---|---|---|
Tab | 选项卡分隔符 | type: Tab |
Palette | 字段分组 | type: Palette |
Linebreak | 调色板中的换行 | type: Linebreak |
FlexForm | FlexForm 容器 | type: FlexForm |
Json | JSON 字段 | type: Json |
fields:
- identifier: my_field
type: Text
label: 我的字段标签 # 静态标签(或使用 labels.xlf)
description: 帮助文本 # 字段描述
required: true # 使字段为必填项
default: "默认值" # 默认值
placeholder: "输入文本..." # 占位符文本
prefixField: false # 为此字段禁用前缀
useExistingField: true # 重用现有的 TCA 字段
displayCond: 'FIELD:other:=:1' # 条件显示
onChange: reload # 更改时重新加载表单
仅限 TCA 的选项: 像
appearance/behaviour这样的键属于生成的 TCA,并不总是在 Content Blocks YAML 中。如果模式拒绝它们,请在生成后为该字段添加 TCA 覆盖(参见 Content Blocks 文档中关于扩展 TCA 的部分)。
fields:
- identifier: gallery_images
type: File
allowed: common-image-types
minitems: 1
maxitems: 10
fields:
- identifier: layout
type: Select
renderType: selectSingle
default: default
items:
- label: 默认布局
value: default
- label: 宽布局
value: wide
- label: 紧凑布局
value: compact
fields:
- identifier: accordion_items
type: Collection
labelField: title
minitems: 1
maxitems: 20
appearance:
collapseAll: true
levelLinksPosition: both
fields:
- identifier: title
type: Text
required: true
- identifier: content
type: Textarea
enableRichtext: true
- identifier: is_open
type: Checkbox
label: 初始展开
Content Blocks 自动为字段标识符添加前缀,以避免冲突。
# 完整前缀(默认):myvendor_myblock_fieldname
name: myvendor/my-block
prefixFields: true
prefixType: full
# 仅供应商前缀:myvendor_fieldname
name: myvendor/my-block
prefixFields: true
prefixType: vendor
# 自定义供应商前缀:tx_custom_fieldname
name: myvendor/my-block
prefixFields: true
prefixType: vendor
vendorPrefix: tx_custom
# 无前缀(谨慎使用!)
name: myvendor/my-block
prefixFields: false
fields:
- identifier: my_custom_field
type: Text
prefixField: false # 此字段不会被添加前缀
<!-- 基本字段访问 -->
{data.header}
{data.my_field}
<!-- 记录元数据 -->
{data.uid}
{data.pid}
{data.languageId}
{data.mainType} <!-- 表名:tt_content -->
{data.recordType} <!-- CType:myvendor_heroblock -->
{data.fullType} <!-- tt_content.myvendor_heroblock -->
<!-- 原始数据库值 -->
{data.rawRecord.some_field}
<!-- 系统属性 -->
{data.systemProperties.createdAt}
{data.systemProperties.lastUpdatedAt}
{data.systemProperties.sorting}
{data.systemProperties.disabled}
<!-- 语言信息 -->
{data.languageInfo.translationParent}
{data.languageInfo.translationSource}
<!-- 关系会自动解析! -->
<f:for each="{data.gallery_images}" as="image">
<f:image image="{image}" width="400"/>
</f:for>
<!-- 嵌套集合 -->
<f:for each="{data.accordion_items}" as="item">
<h3>{item.title}</h3>
<f:format.html>{item.content}</f:format.html>
</f:for>
<!-- 从 assets 文件夹包含 CSS -->
<f:asset.css identifier="my-block-css" href="{cb:assetPath()}/frontend.css"/>
<!-- 从 assets 文件夹包含 JS -->
<f:asset.script identifier="my-block-js" src="{cb:assetPath()}/frontend.js"/>
<!-- 跨块资源引用 -->
<f:asset.css identifier="shared-css" href="{cb:assetPath(name: 'vendor/other-block')}/shared.css"/>
<!-- 访问 labels.xlf 翻译 -->
<f:translate key="{cb:languagePath()}:my_label"/>
<!-- 跨块翻译 -->
<f:translate key="{cb:languagePath(name: 'vendor/other-block')}:shared_label"/>
向现有表(如 tx_news)添加自定义类型:
# EXT:my_sitepackage/ContentBlocks/RecordTypes/custom-news/config.yaml
name: myvendor/custom-news
table: tx_news_domain_model_news
typeName: custom_news
fields:
- identifier: title
useExistingField: true
- identifier: custom_field
type: Text
# 1. 创建新的 Content Block
ddev typo3 make:content-block
# 2. 清除系统缓存
ddev typo3 cache:flush -g system
# 3. 更新数据库模式
ddev typo3 extension:setup --extension=my_sitepackage
# 替代方案:在 TYPO3 后端使用数据库分析器
# 管理工具 > 维护 > 分析数据库结构
如果安装了 webprofil/make:
# 使用 webprofil/make 创建 Content Block
ddev make:content_blocks
# 清除缓存并更新数据库(推荐使用 Core CLI)
ddev typo3 cache:flush
ddev typo3 extension:setup --extension=my_sitepackage
# `database:updateschema` 仅在 helhum/typo3-console 中存在 —— 不要假设它在纯 Core 项目中可用
创建具有正确表名的记录类型后,生成 Extbase 模型:
# 如果 typo3:make:model 可用
ddev typo3 make:model --extension=my_sitepackage
# 生成存储库
ddev typo3 make:repository --extension=my_sitepackage
在项目根目录创建 content-blocks.yaml 以设置默认值:
# content-blocks.yaml
vendor: myvendor
extension: my_sitepackage
content-type: content-element
skeleton-path: content-blocks-skeleton
config:
content-element:
basics:
- TYPO3/Header
- TYPO3/Appearance
- TYPO3/Links
- TYPO3/Categories
group: default
prefixFields: true
prefixType: full
record-type:
prefixFields: true
prefixType: vendor
vendorPrefix: tx_mysitepackage
为记录类型使用兼容 Extbase 的表名:
table: tx_myextension_domain_model_myrecord
尽可能重用现有字段:
使用选项卡和调色板对相关字段进行分组:
使用有意义的标识符(snake_case):
更改后清除缓存:
ddev typo3 cache:flush -g system ddev typo3 extension:setup --extension=my_sitepackage
对所有面向用户的标签使用 labels.xlf
不要使用原始 SQL - Content Blocks 会自动生成模式
不要重复 TCA - Config.yaml 是单一事实来源
不要为 Extbase 集成使用短表名:
table: team_member
# ✅ 正确
table: tx_mysitepackage_domain_model_teammember
4. 不要在标识符中使用短横线:
# ❌ 错误
identifier: hero-image
# ✅ 正确
identifier: hero_image
5. 当在多个地方使用 foreign_table 时,不要忘记 shareAcross 选项
# 清除所有缓存
ddev typo3 cache:flush
# 重建类加载
ddev composer dump-autoload
# 检查扩展设置
ddev typo3 extension:setup --extension=my_sitepackage
# 更新数据库模式(Core)
ddev typo3 extension:setup --extension=my_sitepackage
# 仅限 typo3-console:ddev typo3 database:updateschema
# 或使用比较工具
# 管理工具 > 维护 > 分析数据库结构
Compatibility: This skill targets TYPO3 v14.x with Content Blocks 2.x. Always match the Packagist
friendsoftypo3/content-blocksconstraint to your Core version. For Content Blocks 1.x on TYPO3 v13 , upstream requires TYPO3 ≥ 13.4 (typo3/cms-core: ^13.4) — confirm on Packagist. Examples use TYPO3 v14 APIs and CB 2.x; adjustcomposer.jsonif upstream constraints differ.
TYPO3 API First: Always use TYPO3's built-in APIs, core features, and established conventions before creating custom implementations. Do not reinvent what TYPO3 already provides. Always verify that the APIs and methods you use exist and are not deprecated in TYPO3 v14 by checking the official TYPO3 documentation.
Content Blocks is the modern approach to creating custom content types in TYPO3. It eliminates redundancy by providing a single YAML configuration that generates:
| Traditional Approach | Content Blocks Approach |
|---|---|
| Multiple TCA files | One config.yaml |
| Manual SQL definitions | Auto-generated schema |
| Separate TypoScript | Auto-registered rendering |
| Scattered translations | Single labels.xlf |
| Complex setup | Simple folder structure |
# Install via Composer (DDEV recommended)
ddev composer require friendsoftypo3/content-blocks
# After installation, clear caches
ddev typo3 cache:flush
Version constraint: Content Blocks 1.x requires TYPO3 ≥ 13.4 (
typo3/cms-core: ^13.4in the package). TYPO3 13.1–13.3 do not satisfy that Composer constraint.
For non-composer installations, deny web access to ContentBlocks folder:
# .htaccess addition
RewriteRule (?:typo3conf/ext|typo3/sysext|typo3/ext)/[^/]+/(?:Configuration|ContentBlocks|Resources/Private|Tests?|Documentation|docs?)/ - [F]
Content Blocks supports four content types:
| Type | Folder | Table | Use Case |
|---|---|---|---|
ContentElements | ContentBlocks/ContentElements/ | tt_content | Frontend content (hero, accordion, CTA) |
RecordTypes | ContentBlocks/RecordTypes/ | Custom/existing | Structured records (news, products, team) |
PageTypes |
EXT:my_sitepackage/
└── ContentBlocks/
├── ContentElements/
│ └── my-hero/
│ ├── assets/
│ │ └── icon.svg
│ ├── language/
│ │ └── labels.xlf
│ ├── templates/
│ │ ├── backend-preview.fluid.html
│ │ ├── frontend.fluid.html
│ │ └── partials/
│ └── config.yaml
├── RecordTypes/
│ └── my-record/
│ ├── assets/
│ │ └── icon.svg
│ ├── language/
│ │ └── labels.xlf
│ └── config.yaml
├── PageTypes/
│ └── blog-article/
│ ├── assets/
│ │ ├── icon.svg
│ │ ├── icon-hide-in-menu.svg
│ │ └── icon-root.svg
│ ├── language/
│ │ └── labels.xlf
│ ├── templates/
│ │ └── backend-preview.fluid.html
│ └── config.yaml
└── FileTypes/
└── image-extended/
├── language/
│ └── labels.xlf
└── config.yaml
# Interactive mode
ddev typo3 make:content-block
# One-liner
ddev typo3 make:content-block \
--content-type="content-element" \
--vendor="myvendor" \
--name="hero-banner" \
--title="Hero Banner" \
--extension="my_sitepackage"
# After creation, update database
ddev typo3 cache:flush -g system
ddev typo3 extension:setup --extension=my_sitepackage
List under basics: to pull in Core field groups: TYPO3/Header , TYPO3/Appearance , TYPO3/Links , TYPO3/Categories. See the Content Blocks basics reference.
# EXT:my_sitepackage/ContentBlocks/ContentElements/hero-banner/config.yaml
name: myvendor/hero-banner
fields:
- identifier: header
useExistingField: true
- identifier: bodytext
useExistingField: true
# EXT:my_sitepackage/ContentBlocks/ContentElements/hero-banner/config.yaml
name: myvendor/hero-banner
group: default
description: "A full-width hero banner with image and CTA"
prefixFields: true
prefixType: full
basics:
- TYPO3/Appearance
- TYPO3/Links
fields:
- identifier: header
useExistingField: true
- identifier: subheadline
type: Text
label: Subheadline
- identifier: hero_image
type: File
minitems: 1
maxitems: 1
allowed: common-image-types
- identifier: cta_link
type: Link
label: Call to Action Link
- identifier: cta_text
type: Text
label: Button Text
<!-- templates/frontend.fluid.html -->
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
xmlns:cb="http://typo3.org/ns/TYPO3/CMS/ContentBlocks/ViewHelpers"
data-namespace-typo3-fluid="true">
<f:asset.css identifier="hero-banner-css" href="{cb:assetPath()}/frontend.css"/>
<section class="hero-banner">
<f:if condition="{data.hero_image}">
<f:for each="{data.hero_image}" as="image">
<f:image image="{image}" alt="{data.header}" class="hero-image"/>
</f:for>
</f:if>
<div class="hero-content">
<h1>{data.header}</h1>
<f:if condition="{data.subheadline}">
<p class="subheadline">{data.subheadline}</p>
</f:if>
<f:if condition="{data.cta_link}">
<f:link.typolink parameter="{data.cta_link}" class="btn btn-primary">
{data.cta_text -> f:or(default: 'Learn more')}
</f:link.typolink>
</f:if>
</div>
</section>
</html>
<!-- templates/backend-preview.fluid.html -->
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
xmlns:be="http://typo3.org/ns/TYPO3/CMS/Backend/ViewHelpers"
data-namespace-typo3-fluid="true">
<div class="content-block-preview">
<strong>{data.header}</strong>
<f:if condition="{data.subheadline}">
<br/><em>{data.subheadline}</em>
</f:if>
<f:if condition="{data.hero_image}">
<f:for each="{data.hero_image}" as="image">
<be:thumbnail image="{image}" width="100" height="100"/>
</f:for>
</f:if>
</div>
</html>
Record Types create custom database tables for structured data like teams, products, events, etc.
IMPORTANT: For Extbase compatibility, use the tx_extensionkey_domain_model_* naming convention:
# ✅ CORRECT - Extbase compatible table name
name: myvendor/team-member
table: tx_mysitepackage_domain_model_teammember
labelField: name
fields:
- identifier: name
type: Text
- identifier: position
type: Text
- identifier: email
type: Email
- identifier: photo
type: File
allowed: common-image-types
maxitems: 1
# ❌ WRONG - Short table names don't work with Extbase
name: myvendor/team-member
table: team_member # Won't work with Extbase!
# EXT:my_sitepackage/ContentBlocks/RecordTypes/team-member/config.yaml
name: myvendor/team-member
table: tx_mysitepackage_domain_model_teammember
labelField: name
fields:
- identifier: name
type: Text
# EXT:my_sitepackage/ContentBlocks/RecordTypes/team-member/config.yaml
name: myvendor/team-member
table: tx_mysitepackage_domain_model_teammember
labelField: name
fallbackLabelFields:
- email
languageAware: true
workspaceAware: true
sortable: true
softDelete: true
trackCreationDate: true
trackUpdateDate: true
internalDescription: true
restriction:
disabled: true
startTime: true
endTime: true
userGroup: true # fe_group visibility fields when applicable
security:
ignorePageTypeRestriction: true # Allow on normal pages
fields:
- identifier: name
type: Text
required: true
- identifier: position
type: Text
- identifier: email
type: Email
- identifier: phone
type: Text
- identifier: bio
type: Textarea
enableRichtext: true
- identifier: photo
type: File
allowed: common-image-types
maxitems: 1
- identifier: social_links
type: Collection
labelField: platform
fields:
- identifier: platform
type: Select
renderType: selectSingle
items:
- label: LinkedIn
value: linkedin
- label: Twitter/X
value: twitter
- label: GitHub
value: github
- identifier: url
type: Link
Content Blocks exposes many optional root keys on record types — always confirm names against the current Record Types YAML reference. Commonly used flags include:
| Option | Role |
|---|---|
editLocking | Editor locking behaviour |
sortField / sortable | Manual sorting (sorting column) |
rootLevelType | Allow records at PID 0 |
readOnly | Read-only in FormEngine |
adminOnly | Visible to admins only |
Create multiple types for one table:
# EXT:my_sitepackage/ContentBlocks/RecordTypes/person-employee/config.yaml
name: myvendor/person-employee
table: tx_mysitepackage_domain_model_person
typeField: person_type
typeName: employee
priority: 0 # Integer ordering; higher values load first (higher priority)
labelField: name
languageAware: false
workspaceAware: false
fields:
- identifier: name
type: Text
- identifier: department
type: Text
# EXT:my_sitepackage/ContentBlocks/RecordTypes/person-contractor/config.yaml
name: myvendor/person-contractor
table: tx_mysitepackage_domain_model_person
typeName: contractor
fields:
- identifier: name
type: Text
- identifier: company
type: Text
- identifier: contract_end
type: DateTime
Define a record that can be used in IRRE collections:
# EXT:my_sitepackage/ContentBlocks/RecordTypes/slide/config.yaml
name: myvendor/slide
table: tx_mysitepackage_domain_model_slide
labelField: title
fields:
- identifier: title
type: Text
- identifier: image
type: File
maxitems: 1
- identifier: link
type: Link
# EXT:my_sitepackage/ContentBlocks/ContentElements/slider/config.yaml
name: myvendor/slider
fields:
- identifier: slides
type: Collection
foreign_table: tx_mysitepackage_domain_model_slide
shareAcrossTables: true
shareAcrossFields: true
minitems: 1
Page Types extend the pages table with custom page types – ideal for blog articles, landing pages, news pages, or other page variants with special properties.
| Use Case | Example |
|---|---|
| Structured page properties | Blog with author, teaser image, publish date |
| Plugin integration | News lists, event calendars reading page properties |
| Different page behavior | Landing pages without navigation |
| SEO-specific fields | Custom meta fields per page type |
# EXT:my_sitepackage/ContentBlocks/PageTypes/blog-article/config.yaml
name: myvendor/blog-article
typeName: 1705234567
fields:
- identifier: author_name
type: Text
# EXT:my_sitepackage/ContentBlocks/PageTypes/blog-article/config.yaml
name: myvendor/blog-article
typeName: 1705234567 # Unix timestamp (unique identifier)
group: default # Options: default, link, special
fields:
- identifier: author_name
type: Text
label: Author
required: true
- identifier: teaser_text
type: Textarea
label: Teaser
- identifier: hero_image
type: File
allowed: common-image-types
maxitems: 1
- identifier: publish_date
type: DateTime
label: Publish Date
- identifier: reading_time
type: Number
label: Reading Time (minutes)
| Option | Type | Required | Description |
|---|---|---|---|
typeName | integer | ✓ | Unique doktype number (use Unix timestamp) |
group | string | Group in selector: default, link, special | |
allowedRecordTypes | array |
Reserved typeName values: 199, 254 (cannot be used)
Page Types support state-specific icons. Add these to your assets folder:
ContentBlocks/PageTypes/blog-article/
├── assets/
│ ├── icon.svg # Default icon
│ ├── icon-hide-in-menu.svg # Hidden in menu state
│ └── icon-root.svg # Site root state
└── config.yaml
Create a backend-preview.fluid.html to preview custom page properties:
<!-- templates/backend-preview.fluid.html -->
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
xmlns:be="http://typo3.org/ns/TYPO3/CMS/Backend/ViewHelpers"
data-namespace-typo3-fluid="true">
<div class="card card-size-medium">
<div class="card-body">
<be:link.editRecord uid="{data.uid}" table="{data.mainType}" fields="author_name">
<strong>Author:</strong> {data.author_name}
</be:link.editRecord>
<f:if condition="{data.publish_date}">
<br/><small>Published: <f:format.date format="d.m.Y">{data.publish_date}</f:format.date></small>
</f:if>
</div>
</div>
</html>
Page Types have no automatic frontend rendering. Add the ContentBlocksDataProcessor to your TypoScript:
# Configuration/TypoScript/setup.typoscript
page = PAGE
page {
10 = FLUIDTEMPLATE
10 {
templateName = Default
templateRootPaths.10 = EXT:my_sitepackage/Resources/Private/Templates/
dataProcessing {
# Process Content Blocks page data
1 = content-blocks
}
}
}
Then access fields in your Fluid template:
<!-- Resources/Private/Templates/Default.html -->
<f:if condition="{data.author_name}">
<p class="author">By {data.author_name}</p>
</f:if>
<f:if condition="{data.hero_image}">
<f:for each="{data.hero_image}" as="image">
<f:image image="{image}" class="hero-image"/>
</f:for>
</f:if>
To hide your page type from the "Create new page" drag area:
# Configuration/user.tsconfig
options {
pageTree {
doktypesToShowInNewPageDragArea := removeFromList(1705234567)
}
}
New in version 1.2
File Types extend the sys_file_reference table with custom fields – perfect for photographer credits, copyright notices, or additional reference-level options.
| 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 |
# EXT:my_sitepackage/ContentBlocks/FileTypes/image-extended/config.yaml
name: myvendor/image-extended
typeName: image
fields:
- identifier: photographer
type: Text
label: Photographer
# EXT:my_sitepackage/ContentBlocks/FileTypes/image-extended/config.yaml
name: myvendor/image-extended
typeName: image
prefixFields: false # Keep original column names
fields:
- identifier: image_overlay_palette
type: Palette
label: 'LLL:EXT:core/Resources/Private/Language/locallang_tca.xlf:sys_file_reference.imageoverlayPalette'
fields:
# Reuse existing TYPO3 core fields
- identifier: alternative
useExistingField: true
- identifier: description
useExistingField: true
- type: Linebreak
- identifier: link
useExistingField: true
- identifier: title
useExistingField: true
- type: Linebreak
# Custom fields
- identifier: photographer
type: Text
label: Photographer
- identifier: copyright
type: Text
label: Copyright Notice
- identifier: source_url
type: Link
label: Source URL
- type: Linebreak
- identifier: crop
useExistingField: true
| Option | Type | Required | Description |
|---|---|---|---|
typeName | string | ✓ | One of: text, image, audio, video, application |
prefixFields | boolean | Whether to prefix field identifiers with the Content Block name (often for File Types to keep shared field names) |
| Use Case | Fields to Add |
|---|---|
| Photography agency | photographer, copyright, license_type, expiry_date |
| Video platform | director, duration, transcript, subtitles |
| Document management | document_version, , |
In Fluid templates, access custom metadata through FAL references:
<f:for each="{data.images}" as="image">
<figure>
<f:image image="{image}" alt="{image.alternative}"/>
<f:if condition="{image.properties.photographer}">
<figcaption>
Photo: {image.properties.photographer}
<f:if condition="{image.properties.copyright}">
| © {image.properties.copyright}
</f:if>
</figcaption>
</f:if>
</figure>
</f:for>
| Type | Description | Example |
|---|---|---|
Text | Single line text | type: Text |
Textarea | Multi-line text | type: Textarea |
Email | Email address | type: Email |
Link |
| Type | Description | Example |
|---|---|---|
File | File references (FAL) | type: File |
Relation | Record relations | type: Relation |
Select | Dropdown selection | type: Select |
Category |
| Type | Description | Example |
|---|---|---|
Tab | Tab separator | type: Tab |
Palette | Group fields | type: Palette |
Linebreak | Line break in palette | type: Linebreak |
FlexForm |
fields:
- identifier: my_field
type: Text
label: My Field Label # Static label (or use labels.xlf)
description: Help text # Field description
required: true # Make field required
default: "Default value" # Default value
placeholder: "Enter text..." # Placeholder text
prefixField: false # Disable prefixing for this field
useExistingField: true # Reuse existing TCA field
displayCond: 'FIELD:other:=:1' # Conditional display
onChange: reload # Reload form on change
TCA-only options: Keys like
appearance/behaviourbelong in generated TCA, not always in Content Blocks YAML. If the schema rejects them, add a TCA override for that field after generation (see Content Blocks docs on extending TCA).
fields:
- identifier: gallery_images
type: File
allowed: common-image-types
minitems: 1
maxitems: 10
fields:
- identifier: layout
type: Select
renderType: selectSingle
default: default
items:
- label: Default Layout
value: default
- label: Wide Layout
value: wide
- label: Compact Layout
value: compact
fields:
- identifier: accordion_items
type: Collection
labelField: title
minitems: 1
maxitems: 20
appearance:
collapseAll: true
levelLinksPosition: both
fields:
- identifier: title
type: Text
required: true
- identifier: content
type: Textarea
enableRichtext: true
- identifier: is_open
type: Checkbox
label: Initially Open
Content Blocks automatically prefixes field identifiers to avoid collisions.
# Full prefix (default): myvendor_myblock_fieldname
name: myvendor/my-block
prefixFields: true
prefixType: full
# Vendor prefix only: myvendor_fieldname
name: myvendor/my-block
prefixFields: true
prefixType: vendor
# Custom vendor prefix: tx_custom_fieldname
name: myvendor/my-block
prefixFields: true
prefixType: vendor
vendorPrefix: tx_custom
# No prefix (use with caution!)
name: myvendor/my-block
prefixFields: false
fields:
- identifier: my_custom_field
type: Text
prefixField: false # This field won't be prefixed
<!-- Basic field access -->
{data.header}
{data.my_field}
<!-- Record metadata -->
{data.uid}
{data.pid}
{data.languageId}
{data.mainType} <!-- Table name: tt_content -->
{data.recordType} <!-- CType: myvendor_heroblock -->
{data.fullType} <!-- tt_content.myvendor_heroblock -->
<!-- Raw database values -->
{data.rawRecord.some_field}
<!-- System properties -->
{data.systemProperties.createdAt}
{data.systemProperties.lastUpdatedAt}
{data.systemProperties.sorting}
{data.systemProperties.disabled}
<!-- Language info -->
{data.languageInfo.translationParent}
{data.languageInfo.translationSource}
<!-- Relations are auto-resolved! -->
<f:for each="{data.gallery_images}" as="image">
<f:image image="{image}" width="400"/>
</f:for>
<!-- Nested collections -->
<f:for each="{data.accordion_items}" as="item">
<h3>{item.title}</h3>
<f:format.html>{item.content}</f:format.html>
</f:for>
<!-- Include CSS from assets folder -->
<f:asset.css identifier="my-block-css" href="{cb:assetPath()}/frontend.css"/>
<!-- Include JS from assets folder -->
<f:asset.script identifier="my-block-js" src="{cb:assetPath()}/frontend.js"/>
<!-- Cross-block asset reference -->
<f:asset.css identifier="shared-css" href="{cb:assetPath(name: 'vendor/other-block')}/shared.css"/>
<!-- Access labels.xlf translations -->
<f:translate key="{cb:languagePath()}:my_label"/>
<!-- Cross-block translation -->
<f:translate key="{cb:languagePath(name: 'vendor/other-block')}:shared_label"/>
Add custom types to existing tables (like tx_news):
# EXT:my_sitepackage/ContentBlocks/RecordTypes/custom-news/config.yaml
name: myvendor/custom-news
table: tx_news_domain_model_news
typeName: custom_news
fields:
- identifier: title
useExistingField: true
- identifier: custom_field
type: Text
# 1. Create new Content Block
ddev typo3 make:content-block
# 2. Clear system caches
ddev typo3 cache:flush -g system
# 3. Update database schema
ddev typo3 extension:setup --extension=my_sitepackage
# Alternative: Use Database Analyzer in TYPO3 Backend
# Admin Tools > Maintenance > Analyze Database Structure
If webprofil/make is installed:
# Create Content Block with webprofil/make
ddev make:content_blocks
# Clear caches and update database (prefer Core CLI)
ddev typo3 cache:flush
ddev typo3 extension:setup --extension=my_sitepackage
# `database:updateschema` exists only with helhum/typo3-console — do not assume it in plain Core projects
After creating Record Types with proper table names, generate Extbase models:
# If typo3:make:model is available
ddev typo3 make:model --extension=my_sitepackage
# Generate repository
ddev typo3 make:repository --extension=my_sitepackage
Create a content-blocks.yaml in project root for default settings:
# content-blocks.yaml
vendor: myvendor
extension: my_sitepackage
content-type: content-element
skeleton-path: content-blocks-skeleton
config:
content-element:
basics:
- TYPO3/Header
- TYPO3/Appearance
- TYPO3/Links
- TYPO3/Categories
group: default
prefixFields: true
prefixType: full
record-type:
prefixFields: true
prefixType: vendor
vendorPrefix: tx_mysitepackage
Use Extbase-compatible table names for Record Types:
table: tx_myextension_domain_model_myrecord
Reuse existing fields when possible:
Group related fields with Tabs and Palettes:
Use meaningful identifiers (snake_case):
Clear caches after changes :
ddev typo3 cache:flush -g system ddev typo3 extension:setup --extension=my_sitepackage
Use labels.xlf for all user-facing labels
Don't use raw SQL - Content Blocks generates schema automatically
Don't duplicate TCA - Config.yaml is the single source of truth
Don't use short table names for Extbase integration:
table: team_member
# ✅ Correct
table: tx_mysitepackage_domain_model_teammember
4. Don't use dashes in identifiers :
# ❌ Wrong
identifier: hero-image
# ✅ Correct
identifier: hero_image
5. Don't forget shareAcross options when using foreign_table in multiple places
# Clear all caches
ddev typo3 cache:flush
# Rebuild class loading
ddev composer dump-autoload
# Check extension setup
ddev typo3 extension:setup --extension=my_sitepackage
# Update database schema (Core)
ddev typo3 extension:setup --extension=my_sitepackage
# With typo3-console only: ddev typo3 database:updateschema
# Or use Compare Tool
# Admin Tools > Maintenance > Analyze Database Structure
Use TYPO3 v14.1+ with Content Blocks 2.x (friendsoftypo3/content-blocks currently requires typo3/cms-core: ^14.1 — confirm on Packagist).
// ext_emconf.php — TYPO3 v14.1+ + Content Blocks 2.x
'depends' => [
'typo3' => '14.1.0-14.99.99',
'content_blocks' => '2.0.0-2.99.99',
],
For migration between classic TYPO3 extensions and Content Blocks, see the dedicated migration skill:
If extensions don't support TYPO3 v14 yet, fork and update:
# Add private fork as VCS repository in composer.json
# Then update extension for v14 using typo3-rector and typo3-update skills
Required private forks for webconsulting stack:
webprofil/wp-t3monitoring-client (^13 → ^14)webprofil/deployer (^13 → ^14)webprofil/crawler (^1.0 → compatible with v14)webprofil/make (^1.1 → compatible with v14)The following changes affect Content Blocks development on TYPO3 v14 only.
country [v14 only]TYPO3 v14 introduces a native country TCA type (#99911). Content Blocks can use this for country selection fields. Check Content Blocks YAML documentation for support of this field type.
itemsProcessors [v14 only]New itemsProcessors option (#107889) enables dynamic item generation for select fields. Content Blocks may expose this via YAML configuration for advanced select field customization.
ctrl properties (#108027) — title, label, and other ctrl properties can now be overridden per record type in the types section.Content Block Fluid templates must comply with Fluid 5.0 strict typing:
_myVar).TYPO3 v14.1 integrates content_defender functionality into Core. Backend layouts can now restrict which Content Elements (including Content Blocks) are allowed per colPos without third-party extensions.
This skill incorporates information from the official Content Blocks documentation maintained by the TYPO3 Content Types Team and Friends of TYPO3.
Original documentation: https://docs.typo3.org/p/friendsoftypo3/content-blocks/
Adapted by webconsulting.at for this skill collection
Source: https://github.com/dirnbauer/webconsulting-skills Thanks to Netresearch DTT GmbH for their contributions to the TYPO3 community.
Weekly Installs
69
Repository
GitHub Stars
21
First Seen
Jan 22, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode63
gemini-cli63
codex62
cursor60
github-copilot59
kimi-cli58
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
127,000 周安装
AI Logo Creator - 专业品牌标识设计工具,几何极简矢量风格生成
148 周安装
AWS Azure GCP云成本优化策略:降低云支出、调整资源规模、实施成本治理
149 周安装
Playwright CLI 技能:终端浏览器自动化与测试指南 | 无需全局安装
148 周安装
上下文网络生命周期管理:构建持久化项目知识框架,提升AI智能体效能
145 周安装
RealityKit 开发指南:ECS 架构构建 AR 与 3D 应用 | iOS & visionOS
145 周安装
GitHub Actions专家指南:CI/CD工作流优化、安全实践与自定义开发
145 周安装
ContentBlocks/PageTypes/pages |
| Custom page types (blog, landing page) |
FileTypes | ContentBlocks/FileTypes/ | sys_file_reference | Extended file references (photographer, copyright) |
hideAtCopy / appendLabelAtCopy | Copy behaviour |
group | Backend selector grouping |
Record types allowed on this doktype (default includes pages, sys_category, sys_file_reference, sys_file_collection; * wildcard possible — see official Page Types API) |
falseauthorconfidentiality| E-commerce | product_sku, variant_color, variant_size |
| Link/URL |
type: Link |
Number | Integer/Float | type: Number (+ format: integer or format: decimal as needed; legacy YAML sometimes used a non-existent Integer type — use Number) |
DateTime | Date and/or time | type: DateTime |
Color | Color picker | type: Color |
Checkbox | Boolean checkbox | type: Checkbox |
Radio | Radio buttons | type: Radio |
Slug | URL slug | type: Slug |
Password | Password field | type: Password |
Basic | Shared “basic” field helper | type: Basic |
Country | Country selection (aligns with TCA country where supported) | type: Country |
Pass | Virtual field, not visible in the backend; used for storing data handled by extension logic | type: Pass |
SelectNumber | Select with numeric values | type: SelectNumber |
Uuid | UUID string | type: Uuid |
| System categories |
type: Category |
Collection | Inline records (IRRE) | type: Collection |
Folder | Folder reference | type: Folder |
Language | Language selector | type: Language |
| FlexForm container |
type: FlexForm |
Json | JSON field | type: Json |