From craft-workspace-webconsulting-skills
Builds TYPO3 Content Blocks content elements styled with shadcn/ui presets, semantic tokens, Fluid atoms, backend previews, icons, and seed data.
How this skill is triggered — by the user, by Claude, or both
Slash command
/craft-workspace-webconsulting-skills:typo3-shadcn-content-elementsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> Source: https://github.com/dirnbauer/webconsulting-skills
Use this skill to build TYPO3 Content Blocks content elements that behave like a coherent shadcn/ui system: preset-driven tokens, shared Fluid atoms/molecules, complete field coverage, useful backend previews, semantic icons, local shadcn registry items, and seed data that makes the styleguide pages credible.
This skill assumes Content Blocks are the source of truth for schema and TYPO3 owns rendering. shadcn/ui is the source for theme tokens, component class contracts, data attributes, states, spacing, borders, radius, and typography.
The styling rule is strict: content elements should not hardcode colors or theme-specific visual values. Raw oklch(), hsl(), rgb(), hex colors, and fixed light/dark assumptions belong in the committed shadcn theme token source only. Templates, element CSS, backend preview CSS, generated icons, and chart scripts should consume semantic tokens or Tailwind/shadcn utility classes.
When creating or overhauling Desiderio shadcn/ui content elements, respect these project-specific rules before general preferences:
templates/frontend.fluid.html (the Content Blocks 2.x default since 2.0.4; plain frontend.html is the legacy 1.x name); backend previews stay in templates/backend-preview.fluid.html.d:layout.section, d:layout.container, d:atom.typography, d:atom.icon, buttons, badges, cards, form controls, tabs, accordions, tables, alerts, dialogs, and chart wrappers.copy_code, preview.uid, or field.headline. Provide English base labels and German labels for editor-facing strings. Use ICU MessageFormat for variable or pluralized labels instead of concatenating strings.LLL: references for labels in Content Blocks YAML, backend previews, and templates. Do not hardcode editor-facing labels in Fluid when they belong in XLIFF.Resources/Public/Js/astro.js. Templates should emit data attributes such as data-astro-counter, data-astro-reveal, data-astro-highlight, data-astro-copy, data-astro-tilt, or data-astro-marquee.<script> blocks to content element templates. Add idempotent behavior to shared JS include files, register them through TypoScript or AssetCollector, and make reduced-motion behavior explicit.data-astro-highlight and the copy control. Keep source text escaped in Fluid and let the runtime decorate tokens after load.Resources/Private/Forms, TypoScript renderers in the Site Set, and typo3/cms-form as a Composer runtime dependency. Do not hand-roll mail forms in Fluid templates.desiderio.forms.*). Use a PSR-14 listener, such as BeforeEmailFinisherInitializedEvent, only to map site-specific sender/receiver options. Do not invent a setup.php mail mapping layer.config.yaml.php scripts/audit-content-elements.php, PHPUnit/static checks, Tailwind sync, registry build when registry files changed, JS syntax checks when shared JS changed, and a browser pass.Establish the preset source.
b4hb38Fyj.npx shadcn@latest info --json in the project when components.json exists. If a TYPO3/non-TS repo fails path resolution, add a small tsconfig.json plus scratch aliases so components, ui, lib, utils, and hooks resolve without copying React runtime code into TYPO3.shadcn create or https://ui.shadcn.com/create?item=preview as a design-system source. Use an Astro scratch app when the user asks for Astro/include-file JavaScript patterns; use a Vite/React scratch app only to inspect primitive class contracts.body[data-shadcn-preset="b4hb38Fyj"]; do not add a runtime preset downloader or binary switcher.:root as the light-mode base and .dark as the dark-mode override, matching shadcn. Do not write content elements that only look correct in one mode.references/shadcn-preset-workflow.md before changing theme tokens or primitive class strings.Audit before editing.
php <skill>/scripts/audit-content-elements.php <repo-root> when working on a repo with ContentBlocks/ContentElements.php scripts/audit-content-elements.php) because it contains repo-specific hard checks for inline styles, raw colors, variant branches, undeclared rendered fields, and seed gaps.fixture_missing_field and collection_child_seed_gap can be soft signals when the project seeder auto-fills missing demo values, but the rendered seeded pages still need a visual pass.f:split(, pipe-delimited links such as Label|https://..., legacy list fields such as features_list, specs_text, row_data, comma-delimited tier_values, and monolithic shadcn2fluid_* fixture maps.references/content-element-contract.md, especially for date/time formatting, typolink attributes, resource paths, and string-only ViewHelpers.Fix the shared component layer first.
Resources/Private/Components atoms/molecules from generated shadcn class contracts before editing hundreds of individual templates.bg-background, text-foreground, bg-card, border-border, ring-ring, text-muted-foreground, bg-primary, and text-primary-foreground.f:asset.script, or TYPO3's AssetCollector. Templates should emit data attributes and JSON payload attributes; they should not contain inline <script> renderers.--chart-1 through --chart-5, idempotent initialization, and no hardcoded color fallbacks.references/styling-token-contract.md before adding or changing element CSS, SVG icon colors, chart colors, shadows, overlays, or backend preview styling.Keep the local shadcn registry valid.
registry.json and build output under a public registry endpoint such as Resources/Public/ShadcnRegistry.components.json registry namespace such as "@desiderio": "Resources/Public/ShadcnRegistry/{name}.json".shadcn:info and registry:build, then run both after changing tokens, runtime assets, or registry item files.shadcn info --json for project configuration and shadcn build --output <dir> for registry output. The upstream registry is framework-agnostic, so a TYPO3 registry item may package Fluid, TypoScript, CSS token sources, JavaScript include files, and Site Settings when the item type describes that contract.Audit each content element against its contract.
references/content-element-contract.md.config.yaml, templates/frontend.fluid.html, language/labels.xlf, assets/icon.svg, CSS/JS assets, backend preview, and seed coverage.config.yaml:title as an editor-facing product name. Prefer names like Text & Media, Image Call to Action, and Logo Cloud Hero over raw slugs such as textmedia, CTA With Image, or Hero Logo Cloud.typo3-translations skill for XLIFF format choices, English/German localization, ICU MessageFormat strings, LLL: references, and localized wizard group labels.config.yaml.Style / variant fields as contracts, not decorative metadata. Keep one only when the value is passed to an existing shadcn-backed Fluid component feature (for example Button/Badge/Alert variants or TabsList default/line) or when the template has a real layout/behavior branch. Do not keep variant fields that only append unused BEM modifier classes.config.yaml, frontend templates, backend previews, and fixtures.assets/frontend.css, use an empty/comment-only marker file when the shared component layer handles all styling. Do not re-add f:asset.css includes or style rules merely to satisfy the file-presence contract.Collection fields for second-level repeatables when the installed Content Blocks version supports nested Collections; keep seed scripts recursive so child rows are created after their parent IRRE rows.Collection field an explicit table: key. Without it, Content Blocks derives the table from the identifier alone, so unrelated elements that pick the same name (rows, posts, column_items, cells, items, links...) silently share one physical table — schema migrations break, foreign_table_parent_uid drifts to the wrong type, and renames lose data. Names like <contentblock-slug>_<identifier> are safe, for example blog_teasers_posts or feature_matrix_rows. See references/content-element-contract.md "Collection Table Naming".Link fields for editor-managed URLs. Keep visible link text in a separate text field and never encode Label|https://... pairs in textareas.Add backend previews for the page/layout module.
references/backend-preview-pattern.md.templates/backend-preview.fluid.html using Content Blocks Preview layout with Content and optionally Footer.<f:section name="Header"></f:section> empty — never render a duplicate headline above the formatted card. The card itself shows the title inside d-ce-preview__title. Removing the section instead of emptying it triggers TYPO3's InvalidSectionException fallback to the standard renderer, which re-adds the duplicate.d-ce-preview__meta, surface the editor-facing element name, the Content Block identifier, the record uid, and the page pid as small pills. Use <f:translate key="LLL:EXT:desiderio/Resources/Private/Language/labels.xlf:preview.uid"/> and :preview.page — never hardcode the labels.Create or refresh icons.
references/icon-pattern.md.assets/icon.svg.var(--icon-color-primary,currentColor), currentColor primary paint, var(--icon-color-accent,currentColor) accent, readable in light and dark.gpt-image-*, first verify the currently available OpenAI image model and API credentials. Use image generation for metaphor boards or visual direction; redraw the final asset as clean, editable SVG because TYPO3 backend icons need tiny, token-colored vectors.Update seed scripts.
{"label": "Docs", "link": "https://example.com/docs"} or link_1_label plus link_1. Do not generate pipe-delimited link strings.fixture_missing_field or collection_child_seed_gap rows but hard template/style checks are clean, improve the project seeder first. Fallback copy should read like real pattern-library content (Pattern Library, realistic product/demo copy, useful CTA labels, valid links, valid icon keys, token names such as primary) and must not expose generic placeholder phrases such as Complete demo content.Select fields over freeform Color fields for elements whose appearance should track theme changes. If an element needs editor color choice, render it through token-backed data attributes or CSS variables and keep raw color values out of fixtures and fallback seed data.Select values against the current config.yaml items before insertion. Stale fixture values from removed style variants should fall back to the configured default instead of seeding inert editor choices.ContentBlocks/ContentElements/<element>/fixture.json file. Do not create or restore monolithic shadcn2fluid_* fixture mappings.Verify and commit in reviewable slices.
npx shadcn@latest info --json and npx shadcn@latest build --output <public-registry-dir> when components.json or registry.json changed.rg -n "<script>|JSON\\.parse" ContentBlocks/ContentElements/*/templates/frontend.fluid.html.This is the single most damaging mistake when authoring Content Blocks. Read this before creating any type: Collection field.
Every type: Collection field generates a separate physical database table. Without an explicit table: key, Content Blocks falls back to using the bare identifier as the table name. That breaks production in three escalating ways:
rows, groups, order, range, system, values, user are MySQL/MariaDB reserved words. Doctrine quotes at runtime so the table works inside TYPO3, but mysqldump, mysqlcheck, ad-hoc CLI queries, schema-diff tools, and IDE introspection all stumble on the unquoted name.posts, column_items, rows, cells, items, links, features, tabs, members, slides, stats, tiers, partners, clients, reviews, routes, metrics, specs, jobs, awards...), Content Blocks merges their schemas into one shared table. The shared table becomes the union of every consuming element's columns, schema migrations get confused, and renaming one block later requires a parent-aware data migration to split records back apart.foreign_table_parent_uid type drift. Older Content Blocks versions created the parent reference column as varchar(255) DEFAULT '' NOT NULL. Newer TCA-driven schema migration wants int unsigned DEFAULT 0 NOT NULL. The migration fails with Truncated incorrect INTEGER value: '' because existing rows hold empty-string values that strict-mode MySQL refuses to coerce. Recovery requires UPDATE <table> SET foreign_table_parent_uid = 0 WHERE foreign_table_parent_uid = '' before the ALTER. Adding table: from the start avoids the legacy column path entirely on fresh tables.type: Collection field without table:.rows, posts, column_items, cells, items, links, features, tabs, members, slides, stats, tiers, groups, users, range, order, system, values as a table: value — they collide with other extensions or with reserved SQL keywords.table: after editor data exists without a parent-aware data migration: dropping a shared table loses every block's content, and renaming without migration orphans the rows.type: Collection field an explicit table: directive in the YAML.<contentblock-slug-as-snake_case>_<collection-identifier>, for example blog_teasers_posts, feature_matrix_rows, footer_mega_column_items, pricing_plan_features, data_table_cells.pricing_plan_features for a features Collection nested inside plans).table: to every Collection in the same pass — schema migrations regress as soon as one block falls through.# Every Collection field that lacks an explicit table: directive (should print nothing).
rg -nP '^\s*type: Collection\s*$' --no-heading -A1 ContentBlocks/ContentElements \
| rg -B1 -v 'table:'
# Bare table names that match MySQL/MariaDB reserved words.
rg -n '^\s+table:\s+(rows|groups|range|order|system|values|user|cross|dense_rank|window)\s*$' \
ContentBlocks/ContentElements
# Bare unprefixed names — risky for cross-extension collision even if not reserved.
rg -nP '^\s+table:\s+[a-z][a-z0-9_]*\s*$' ContentBlocks/ContentElements \
| rg -v '_[a-z]' # everything kept after this filter has no underscore — review by hand.
The full reasoning, migration playbook for an already-shared table, and additional examples live in references/content-element-contract.md "Collection Table Naming".
shadcn2fluid; allowed mentions are limited to package conflicts, migration notes, and tests/docs that explicitly prevent the old package or fixture map from returning.type: Collection field has an explicit table: key with a <contentblock-slug>_<identifier> value. No bare names, no reserved SQL words. Audit grep in "Critical Rules — Collection Table Naming" should print nothing.references/shadcn-preset-workflow.md: scratch-app preset workflow and token expectations.references/styling-token-contract.md: no-hardcoded-style rules, light/dark behavior, and verification scans.references/content-element-contract.md: field/template/label/seed audit contract.references/backend-preview-pattern.md: Content Blocks backend preview pattern.references/icon-pattern.md: TYPO3 backend icon rules.../typo3-translations/SKILL.md: XLIFF, localization, ICU MessageFormat, and LLL: label rules.scripts/audit-content-elements.php <repo-root>: JSON audit for Content Blocks directories.npx claudepluginhub dirnbauer/webconsulting-skillsGuides modeling TYPO3 Content Blocks (config.yaml) for content elements, record types, page types, and file types. Use when creating, migrating, or debugging Content Blocks and friendsoftypo3/content-blocks behavior.
Provides battle-tested TYPO3 Fluid template patterns for v12+ site packages, covering template hierarchy, CMS-first content architecture, responsive images, and WCAG 2.1 AA accessibility.
Recommends and installs shadcn/ui components plus 1,338 premium ShadcnBlocks and 1,189 free components for React/Next.js + Tailwind frontends like landing pages, dashboards, heroes, and pricing sections.