Initial t3bootstrap-skills plugin: three skills for T3Bootstrap on TYPO3 v14
- t3bootstrap-site-package: composer + site sets + when to add a local extension
- t3bootstrap-overrides: 4-layer override surface (Settings → SCSS → Fluid → DataProcessor)
- t3bootstrap-content-elements: 23 t3bs_* CE catalog + migration matrix (HTML/WP/Joomla/older TYPO3) + Flux-bs5 upgrade wizard
Mirrors the structure of wapplersystems/typo3-skills (.claude-plugin/{plugin.json,marketplace.json}, .agents/skills/<name>/{SKILL.md,agents/openai.yaml}).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,417 @@
|
||||
---
|
||||
name: t3bootstrap-content-elements
|
||||
description: Choose the right content element when migrating content into a T3Bootstrap-based TYPO3 v14 site. Covers the full catalog of 23 `t3bs_*` container-based CEs from `t3bootstrap/container-bs5-templates`, the custom CEs from `t3bootstrap/core` (Card, CompareSlider, Countdown, Counterbar, NumberCarousel) and `t3bootstrap/hero-item`, plus a decision matrix for source materials — static HTML/Bootstrap markup, WordPress blocks, Joomla modules, older TYPO3 sites with `flux_bs5_templates` / `gridelements` / `dce` / `bootstrap_package`. Includes the parent-child container nesting rules, the `t3bsContainerBs5MigrateFluxBs5` upgrade wizard and how to run it, the colPos slot conventions, and guidance on when to pick a core CE (`textmedia`, `image`, `header`, `bullets`) over a custom one. Use this skill whenever migrating content TO a T3Bootstrap project, picking which CE to use for a given visual pattern, debugging "child element doesn't appear in parent" issues, or planning a Flux-to-Container content rewrite.
|
||||
---
|
||||
|
||||
# T3Bootstrap Content Elements
|
||||
|
||||
Use this skill to decide **which content element** to use when bringing content into a
|
||||
T3Bootstrap-based TYPO3 v14 project — from static HTML, another CMS, an older TYPO3
|
||||
version, or hand-rebuilt by an editor.
|
||||
|
||||
> **Companion skills:**
|
||||
> - [`t3bootstrap-site-package`](../t3bootstrap-site-package/SKILL.md) — make sure the right packages and Site Sets are present before placing CEs.
|
||||
> - [`t3bootstrap-overrides`](../t3bootstrap-overrides/SKILL.md) — when a stock CE almost fits but you need to tweak its template.
|
||||
|
||||
## The Three CE Layers
|
||||
|
||||
A T3Bootstrap project draws content elements from **three sources**, in order of
|
||||
specificity:
|
||||
|
||||
1. **Core CEs** from TYPO3's `fluid_styled_content` — `textmedia`, `image`, `header`, `bullets`, `table`, `uploads`, `menu_*`, `shortcut`, …
|
||||
T3Bootstrap **rewraps** these via `t3bootstrap/core` (extended `tt_content` fields, Bootstrap-aware Fluid templates).
|
||||
2. **Custom CEs from `t3bootstrap/core`** — `t3bs_card`, `t3bs_compareslider`, `t3bs_countdown`, `t3bs_counterbar`, `t3bs_numbercarousel`. These are **non-container**, single-element CEs with a fixed shape.
|
||||
3. **Container CEs from `t3bootstrap/container-bs5-templates`** — the 23 `t3bs_*` elements that wrap or compose children via `b13/container`.
|
||||
|
||||
**Rule of thumb when migrating:**
|
||||
|
||||
- *Plain prose with optional images* → core `textmedia`. Don't reach for a container.
|
||||
- *Headline + paragraph + image + button, arranged together* → still likely `textmedia` + `t3bs_buttonlink`, **unless** the visual requires Bootstrap card styling.
|
||||
- *Multiple of these arranged in a Bootstrap-styled box* → `t3bs_card` (single) or `t3bs_cards` (grid).
|
||||
- *Anything that **wraps** other content elements* → a container (`t3bs_container`, `t3bs_fluidrow` + `t3bs_column`, …).
|
||||
|
||||
## Core CEs — Use These First
|
||||
|
||||
The core CEs cover most static content. T3Bootstrap doesn't replace them; it gives them
|
||||
better wrappers, frame classes, breakpoint grids and additional fields (`element_classes`,
|
||||
`image_classes`, `imagecols_grid`, `background_media`).
|
||||
|
||||
| Core CType | When to use |
|
||||
| --- | --- |
|
||||
| `textmedia` | Default body content with optional images. Migrating any "paragraph + image" combination. |
|
||||
| `text` | Pure prose, no media. |
|
||||
| `header` | Standalone headline above a section. |
|
||||
| `image` | Image only, optional caption. Migrating image galleries → one `image` per picture. |
|
||||
| `textpic` | Legacy form of textmedia kept for backwards compatibility — prefer `textmedia` for new content. |
|
||||
| `bullets` | Lists. |
|
||||
| `table` | Tabular data. |
|
||||
| `uploads` | File downloads. |
|
||||
| `menu_*` | Sitemap, categorized pages, pages, recently updated, related pages. |
|
||||
| `shortcut` | Reference another tt_content record (useful for "include this CE on multiple pages"). |
|
||||
| `html` | Raw HTML. **Migration source for everything you can't classify yet** — but a follow-up pass should re-classify into proper CEs. |
|
||||
|
||||
T3Bootstrap-extended fields available on every CE:
|
||||
|
||||
- `element_classes` — extra CSS classes on the CE wrapper.
|
||||
- `image_classes` — extra classes on image renderings.
|
||||
- `imagecols_grid` — JSON breakpoint grid for image columns (responsive 1/2/3/4-col layouts).
|
||||
- `background_media` — FAL reference for a section background image/video.
|
||||
- Spacing palette (provided by `t3bootstrap/core`) — responsive padding/margin per breakpoint, stored as JSON in dedicated columns. *(See the spacing-stepper concept memo if extending this.)*
|
||||
|
||||
## Custom Single CEs from `t3bootstrap/core`
|
||||
|
||||
These are not containers — they're standalone elements with a fixed shape. Each is enabled
|
||||
by including the matching Site Set.
|
||||
|
||||
| CType | Site Set | Source | Use for |
|
||||
| --- | --- | --- | --- |
|
||||
| `t3bsCard` (custom card) | `t3bootstrap/card-element` | `vendor/t3bootstrap/core/Configuration/TCA/Overrides/600_content_element_card.php` | A simple card without nested CEs — image, title, text, link. *Use over `t3bs_card` when no nested content elements are needed.* |
|
||||
| `t3bsCompareSlider` | `t3bootstrap/compareslider-element` | `600_content_element_compare_slider.php` | Before/after image comparison with a draggable divider. |
|
||||
| `t3bsCountdown` | `t3bootstrap/countdown-element` | `600_content_element_countdown.php` | Date/time countdown widget. |
|
||||
| `t3bsCounterbar` | `t3bootstrap/counterbar-element` | `202_content_element_counterbar.php` | Animated number counter ("12,000+ customers"). |
|
||||
| Hero | `t3bootstrap/hero-item` | `vendor/t3bootstrap/hero-item/Configuration/TCA/Overrides/tt_content.php` | Full-width banner with title, subtitle, background image/video, CTA. *Use over `t3bs_container` for landing pages.* |
|
||||
| Teaser | `wapplersystems/teaser` | n/a | Image + headline + text teaser block, links to a page. |
|
||||
| Testimonial | `wapplersystems/testimonials` | n/a | Quote + author + photo. |
|
||||
| Slider | `wapplersystems/ws-slider*` | n/a | Each variant (`flexslider`, `swiper`, `tinyslider`, `slick`, `bootstrap`) is one CE. *Use over `t3bs_carousel` when image-only with no inner content.* |
|
||||
|
||||
## Container CEs — The 23 `t3bs_*` Elements
|
||||
|
||||
Defined in `vendor/t3bootstrap/container-bs5-templates/Configuration/TCA/Overrides/tt_content.php`
|
||||
and registered via `b13/container`. **All container slots use the colPos range `21000–21079`**.
|
||||
|
||||
### Layout containers — wrap arbitrary content
|
||||
|
||||
| CType | colPos | Children allowed | Purpose |
|
||||
| --- | --- | --- | --- |
|
||||
| `t3bs_container` | `21001` | any | Bootstrap `.container` / `.container-sm` / `.container-fluid` wrapper. Set `tx_t3bs_container_type` to choose the breakpoint. |
|
||||
| `t3bs_fluidrow` | `21041` | only `t3bs_column` | Bootstrap `.row` with per-breakpoint column grid. |
|
||||
| `t3bs_column` | `21050` | any | A `.col-*` cell. Width per breakpoint configured via TCA. Always a child of `t3bs_fluidrow`. |
|
||||
|
||||
### Content containers — wrap CEs in styled boxes
|
||||
|
||||
| CType | colPos | Purpose |
|
||||
| --- | --- | --- |
|
||||
| `t3bs_card` | `21008` | Bootstrap card with header/image/body/footer regions; children render in the body. |
|
||||
| `t3bs_cards` | `21009` | A **set** of cards rendered as group / deck / grid / columns layout (`tx_t3bs_cards_layout`). Children: any. |
|
||||
| `t3bs_alert` | `21003` | Bootstrap `.alert` (primary/success/danger/warning/info/light/dark) with optional close button. |
|
||||
| `t3bs_panel` | `21005` | Styled panel (legacy Bootstrap-3-style box). |
|
||||
| `t3bs_well` | `21004` | Inset well (small/normal/large via `tx_t3bs_well_style`). |
|
||||
| `t3bs_example` | `21002` | Code-example container (renders the children inside a `.example` box used for documentation pages). |
|
||||
| `t3bs_thumbnail` | `21006` | Image thumbnail with caption. |
|
||||
| `t3bs_media` | `21007` | Bootstrap media object — image flush left or right of text. |
|
||||
|
||||
### Interactive containers — children become panels/slides/items
|
||||
|
||||
| CType | child colPos | Allowed children | Purpose |
|
||||
| --- | --- | --- | --- |
|
||||
| `t3bs_accordion` | `21011` | `t3bs_accordion_item` only | Accordion. Each `t3bs_accordion_item` becomes one collapsible panel. |
|
||||
| `t3bs_accordion_item` | `21019` | any | One accordion panel — contains the body content. |
|
||||
| `t3bs_tabs` | `21021` | `t3bs_tab_item` only | Tab container (tab/pill via `tx_t3bs_tabs_mode`). |
|
||||
| `t3bs_tab_item` | `21029` | any | One tab pane. |
|
||||
| `t3bs_carousel` | `21031` | `t3bs_carousel_item` only | Image/content carousel. Controls/indicators/interval configurable. |
|
||||
| `t3bs_carousel_item` | `21039` | any | One slide. |
|
||||
| `t3bs_timeline` | `21071` | `t3bs_timeline_item` only | Vertical timeline. |
|
||||
| `t3bs_timeline_item` | `21079` | any | One timeline entry. |
|
||||
|
||||
### Navigation containers — buttons and megamenu
|
||||
|
||||
| CType | child colPos | Children | Purpose |
|
||||
| --- | --- | --- | --- |
|
||||
| `t3bs_buttongroup` | `21010` | `t3bs_buttonlink` only | Group of buttons (Bootstrap button group). |
|
||||
| `t3bs_buttonlink` | — | (standalone) | Single button. Standalone CE — can also appear outside a button group. |
|
||||
| `t3bs_megamenu` | `21061` | `t3bs_megamenu_item` only | Megamenu dropdown. |
|
||||
| `t3bs_megamenu_item` | `21069` | any | One megamenu column / sub-section. |
|
||||
|
||||
### Parent-child Rules — Common Pitfalls
|
||||
|
||||
| Symptom | Cause | Fix |
|
||||
| --- | --- | --- |
|
||||
| `t3bs_column` placed without a parent → renders standalone | `t3bs_column` has no UI restriction at root but is only meaningful inside `t3bs_fluidrow`. | Always insert via "create child" inside a `t3bs_fluidrow`. |
|
||||
| `t3bs_accordion_item` rendered outside an accordion | Same — no rendering wrapper. | Same — insert as a child of `t3bs_accordion`. |
|
||||
| Editor can't find `t3bs_carousel_item` in the CE wizard root | Correct — these CTypes are deliberately filtered. | Edit by entering the parent's child slot. |
|
||||
| Carousel/Tabs/Accordion show "0 children" but you added textmedia | You inserted into the parent's *own* colPos (e.g. 0) instead of the parent's *child slot colPos*. | Move the children to the parent's child slot (e.g. `colPos = 21011` for an accordion). |
|
||||
|
||||
## Migration Decision Matrix
|
||||
|
||||
For each source pattern, the recommended T3Bootstrap target.
|
||||
|
||||
### From static HTML / Bootstrap pages
|
||||
|
||||
| Source markup | Target CE |
|
||||
| --- | --- |
|
||||
| `<section>` with `.container` and paragraphs | `t3bs_container` wrapping `textmedia` children, **or** just `textmedia` with `imagecols_grid` if it's a single paragraph block |
|
||||
| `.row > .col-md-4` × N | `t3bs_fluidrow` with N `t3bs_column` children. Set column widths per breakpoint via TCA. |
|
||||
| `.card` block (image + title + body) | `t3bs_card` (with child content for the body) **or** the simpler standalone `t3bsCard` (no children needed) |
|
||||
| `.card-deck` / `.row-cols-md-3 > .col` of cards | `t3bs_cards` with `tx_t3bs_cards_layout = deck` (or `grid-cards`) |
|
||||
| `.accordion` / `<details>` | `t3bs_accordion` + one `t3bs_accordion_item` per item |
|
||||
| Bootstrap `.nav-tabs` / `.nav-pills` | `t3bs_tabs` + `t3bs_tab_item` per tab |
|
||||
| Bootstrap `.carousel` | `t3bs_carousel` + `t3bs_carousel_item` per slide |
|
||||
| `.alert.alert-warning` | `t3bs_alert` with `tx_t3bs_alert_class = warning` |
|
||||
| `.btn.btn-primary` | `t3bs_buttonlink` (with optional `t3bs_buttongroup` parent) |
|
||||
| Hero `<section>` with full-bleed background | `Hero` (from `t3bootstrap/hero-item`) |
|
||||
| Vertical timeline | `t3bs_timeline` + `t3bs_timeline_item` per step |
|
||||
| Before/after slider | `t3bsCompareSlider` |
|
||||
| Animated counter | `t3bsCounterbar` |
|
||||
| Countdown timer | `t3bsCountdown` |
|
||||
| Image gallery | `wapplersystems/filecollection-gallery` set with a `file_collection` CE, **or** N `image` CEs in a `t3bs_fluidrow`. |
|
||||
|
||||
### From WordPress
|
||||
|
||||
| Gutenberg block | Target |
|
||||
| --- | --- |
|
||||
| `core/paragraph` + `core/image` | `textmedia` |
|
||||
| `core/heading` | `header` |
|
||||
| `core/list` | `bullets` |
|
||||
| `core/table` | `table` |
|
||||
| `core/columns` + `core/column` | `t3bs_fluidrow` + `t3bs_column` |
|
||||
| `core/group` (background, padding) | `t3bs_container` |
|
||||
| `core/cover` (full-width image + heading) | `Hero` (from `t3bootstrap/hero-item`) |
|
||||
| `core/buttons` + `core/button` | `t3bs_buttongroup` + `t3bs_buttonlink` |
|
||||
| `core/media-text` | `t3bs_media` |
|
||||
| `core/quote` / `core/pullquote` | `textmedia` with the `Frameless` layout + `element_classes = blockquote` — or a custom `Testimonial` CE if the visual is testimonial-style |
|
||||
| `core/gallery` | `wapplersystems/filecollection-gallery` |
|
||||
| WP CPT (e.g. portfolio item) | A TYPO3 news/blog/address record + custom record sitemap, **not** a CE |
|
||||
| ACF flexible content / page builder layouts | Map each layout to the closest `t3bs_*` container; complex one-offs go in `t3bs_container` with `html` CE child |
|
||||
|
||||
### From Joomla
|
||||
|
||||
| Joomla pattern | Target |
|
||||
| --- | --- |
|
||||
| Joomla article body | `textmedia` (one per paragraph block, or one big with embedded media) |
|
||||
| Module position | A page-level colPos in T3Bootstrap; map module → CE per the rest of this table |
|
||||
| K2 / EasyBlog items | `news` records (via `t3bootstrap/news`) or `blog` posts (`t3bootstrap/blog`) |
|
||||
| RSGallery / Phoca Gallery | `wapplersystems/filecollection-gallery` |
|
||||
| RSForm / Chronoforms | EXT:form via `t3bootstrap/form` set |
|
||||
| Sliders (DJ-ImageSlider, Smart Slider) | Pick a `ws-slider-*` variant per the brief (most projects use `swiper` or `flexslider`) |
|
||||
| Modal / accordion modules | `t3bs_accordion` / `t3bs_tabs` |
|
||||
| YOOtheme widget kit | Map each widget to its `t3bs_*` cousin; for icon + heading + text use `textmedia` with `t3bs_icon` |
|
||||
|
||||
### From older TYPO3 versions
|
||||
|
||||
#### From v9–v12 with `flux_bs5_templates`
|
||||
|
||||
**Use the upgrade wizard.** Don't migrate manually — the wizard preserves child relations,
|
||||
maps FlexForm values to the new dedicated `tx_t3bs_*` columns, and updates `tx_container_parent`.
|
||||
|
||||
```bash
|
||||
# In DDEV, after composer-installing t3bootstrap/container-bs5-templates:
|
||||
ddev exec vendor/bin/typo3 upgrade:run t3bsContainerBs5MigrateFluxBs5
|
||||
|
||||
# Or via the Install Tool: TYPO3 backend → Admin Tools → Upgrade → Upgrade Wizards
|
||||
# → "Migrate flux_bs5_templates content elements to container_bs5_templates" → Execute
|
||||
```
|
||||
|
||||
**Mapping the wizard applies** (source `vendor/t3bootstrap/container-bs5-templates/Classes/Updates/MigrateFluxBs5ToContainerBs5.php`):
|
||||
|
||||
| Old Flux CType | New CType | Notes |
|
||||
| --- | --- | --- |
|
||||
| `fluxbs5templates_container` | `t3bs_container` | FlexForm → `tx_t3bs_container_type` |
|
||||
| `fluxbs5templates_example` | `t3bs_example` | |
|
||||
| `fluxbs5templates_alert` | `t3bs_alert` | FlexForm → `tx_t3bs_alert_class`, `tx_t3bs_alert_block`, `tx_t3bs_alert_close_text` |
|
||||
| `fluxbs5templates_well` | `t3bs_well` | FlexForm → `tx_t3bs_well_style` |
|
||||
| `fluxbs5templates_panel` | `t3bs_panel` | FlexForm → `tx_t3bs_panel_class` |
|
||||
| `fluxbs5templates_thumbnail` | `t3bs_thumbnail` | |
|
||||
| `fluxbs5templates_media` | `t3bs_media` | |
|
||||
| `fluxbs5templates_card` | `t3bs_card` | |
|
||||
| `fluxbs5templates_cards` | `t3bs_cards` | FlexForm → `tx_t3bs_cards_layout`, `_grid`, `_gutter` |
|
||||
| `fluxbs5templates_buttongroup` | `t3bs_buttongroup` | FlexForm → `tx_t3bs_bg_type` |
|
||||
| `fluxbs5templates_accordion` | `t3bs_accordion` | Children rewired to `t3bs_accordion_item`, colPos 21011 |
|
||||
| `fluxbs5templates_tabs` | `t3bs_tabs` | Children to `t3bs_tab_item`, colPos 21021. FlexForm → `tx_t3bs_tabs_mode`, `_direction`, `_stackable`, `_position` |
|
||||
| `fluxbs5templates_carousel` | `t3bs_carousel` | Children to `t3bs_carousel_item`, colPos 21031. FlexForm → controls, indicators, interval, id, color |
|
||||
| `fluxbs5templates_fluidrow` | `t3bs_fluidrow` | Each flex column becomes a `t3bs_column` child at colPos 21041 |
|
||||
| `fluxbs5templates_buttonlink` | `t3bs_buttonlink` | FlexForm → full set of `tx_t3bs_button_*` fields |
|
||||
| `fluxbs5templates_megamenu` | `t3bs_megamenu` | Children to `t3bs_megamenu_item`, colPos 21061 |
|
||||
|
||||
**After the wizard runs:** flush caches (`cache:flush`), update the reference index
|
||||
(`referenceindex:update`), and re-import freshly delta-migrated content from live if you
|
||||
were doing the parallel live→stage migration described in the global instructions.
|
||||
|
||||
#### From v8–v11 with `gridelements`
|
||||
|
||||
No wizard. Map manually:
|
||||
|
||||
| `gridelements_pi1` layout | Target |
|
||||
| --- | --- |
|
||||
| 1-column grid | `t3bs_container` |
|
||||
| 2-column grid | `t3bs_fluidrow` + 2× `t3bs_column` |
|
||||
| 3/4-column grid | `t3bs_fluidrow` + N× `t3bs_column` |
|
||||
| Tabbed grid | `t3bs_tabs` + N× `t3bs_tab_item` |
|
||||
| Accordion grid | `t3bs_accordion` + N× `t3bs_accordion_item` |
|
||||
| Hero grid | `Hero` (from `t3bootstrap/hero-item`) |
|
||||
|
||||
In a migration project: SQL-query `tt_content WHERE CType='gridelements_pi1'`, group by
|
||||
`tx_gridelements_backend_layout`, and rewrite the CType + children's `colPos` (gridelements
|
||||
uses `tx_gridelements_columns` instead of `tx_container_parent`).
|
||||
|
||||
#### From v8–v11 with `dce`
|
||||
|
||||
No wizard. DCE content elements are project-specific. For each DCE:
|
||||
|
||||
1. Look at its rendering template — what HTML does it emit?
|
||||
2. Pick the closest `t3bs_*` CE.
|
||||
3. Map DCE fields → `tx_t3bs_*` columns or extended `tt_content` fields from `t3bootstrap/core`.
|
||||
4. Custom-only DCEs that have no direct equivalent → wrap in `t3bs_container` with an `html` child for the unique markup, plan to replace gradually.
|
||||
|
||||
#### From v11/v12 with `bootstrap_package`
|
||||
|
||||
`bootstrap_package` has a different content element set. Mapping:
|
||||
|
||||
| `bootstrap_package` CType | T3Bootstrap CType |
|
||||
| --- | --- |
|
||||
| `bootstrap_package_card_group` | `t3bs_cards` |
|
||||
| `bootstrap_package_carousel` | `t3bs_carousel` |
|
||||
| `bootstrap_package_accordion` | `t3bs_accordion` |
|
||||
| `bootstrap_package_tabs` | `t3bs_tabs` |
|
||||
| `bootstrap_package_modal` | No direct CE — use `t3bs_buttonlink` with `tx_t3bs_button_modal = 1` and a referenced text block |
|
||||
| `bootstrap_package_listgroup` | `bullets` with `element_classes = list-group` |
|
||||
| `bootstrap_package_panel` | `t3bs_panel` |
|
||||
| `bootstrap_package_jumbotron` | `Hero` (`t3bootstrap/hero-item`) |
|
||||
| `bootstrap_package_textmedia` | core `textmedia` |
|
||||
| `bootstrap_package_icon_group` | `t3bs_fluidrow` + `t3bs_column` per icon, `textmedia` with `tx_t3bs_icon` set inside each |
|
||||
|
||||
`bootstrap_package`'s `bootstrap_package_card_group` already uses child elements wired via
|
||||
TCA — copy the child relationships rather than rebuild.
|
||||
|
||||
## When to Pick Which Layer (Cheat Sheet)
|
||||
|
||||
```
|
||||
Is it a wrapping/grouping element (multiple CEs sit inside)?
|
||||
├── YES → container CE
|
||||
│ ├── styled box around children? → t3bs_card / t3bs_alert / t3bs_panel / t3bs_well
|
||||
│ ├── tabs/accordion/carousel? → t3bs_tabs / t3bs_accordion / t3bs_carousel
|
||||
│ ├── timeline? → t3bs_timeline
|
||||
│ ├── grid? → t3bs_fluidrow + t3bs_column
|
||||
│ ├── button group? → t3bs_buttongroup
|
||||
│ └── transparent / just structure? → t3bs_container
|
||||
│
|
||||
└── NO → single CE
|
||||
├── prose + maybe one image? → textmedia
|
||||
├── headline only? → header
|
||||
├── image-only? → image
|
||||
├── list? → bullets
|
||||
├── table? → table
|
||||
├── hero banner? → Hero (hero-item)
|
||||
├── card without nested CEs? → t3bsCard (card-element)
|
||||
├── before/after slider? → t3bsCompareSlider
|
||||
├── animated number? → t3bsCounterbar
|
||||
├── countdown? → t3bsCountdown
|
||||
├── testimonial? → wapplersystems/testimonials
|
||||
├── slider with image-only slides? → ws-slider variant
|
||||
├── button-only? → t3bs_buttonlink (standalone)
|
||||
└── still no fit? → html (temporary, plan to re-classify)
|
||||
```
|
||||
|
||||
## colPos Map (Reference)
|
||||
|
||||
When debugging "where did my child go?" — the colPos numbers reserved by
|
||||
`t3bootstrap/container-bs5-templates`:
|
||||
|
||||
```
|
||||
21001 t3bs_container (single slot)
|
||||
21002 t3bs_example
|
||||
21003 t3bs_alert
|
||||
21004 t3bs_well
|
||||
21005 t3bs_panel
|
||||
21006 t3bs_thumbnail
|
||||
21007 t3bs_media
|
||||
21008 t3bs_card
|
||||
21009 t3bs_cards
|
||||
21010 t3bs_buttongroup (allows only t3bs_buttonlink)
|
||||
21011 t3bs_accordion (allows only t3bs_accordion_item)
|
||||
21019 t3bs_accordion_item
|
||||
21021 t3bs_tabs (allows only t3bs_tab_item)
|
||||
21029 t3bs_tab_item
|
||||
21031 t3bs_carousel (allows only t3bs_carousel_item)
|
||||
21039 t3bs_carousel_item
|
||||
21041 t3bs_fluidrow (allows only t3bs_column)
|
||||
21050 t3bs_column
|
||||
21061 t3bs_megamenu (allows only t3bs_megamenu_item)
|
||||
21069 t3bs_megamenu_item
|
||||
21071 t3bs_timeline (allows only t3bs_timeline_item)
|
||||
21079 t3bs_timeline_item
|
||||
```
|
||||
|
||||
`tx_container_parent` on a child row stores the parent's `uid`; the child's `colPos` is set
|
||||
to the parent's slot. Direct SQL example:
|
||||
|
||||
```sql
|
||||
-- All children of accordion uid=42
|
||||
SELECT uid, CType, header, colPos, tx_container_parent
|
||||
FROM tt_content
|
||||
WHERE tx_container_parent = 42 AND colPos = 21011;
|
||||
```
|
||||
|
||||
## Content Defender Hints (TYPO3 v14.1+)
|
||||
|
||||
`content_defender` is part of TYPO3 v14.1 Core. The container declarations in
|
||||
`t3bootstrap/container-bs5-templates` already use the `allowed` constraint on the slot
|
||||
arrays:
|
||||
|
||||
```php
|
||||
$registerContainer($registry, 't3bs_accordion', $ll . 'ce.accordion',
|
||||
[[['name' => $ll . 'slot.item', 'colPos' => 21011, 'allowed' => ['CType' => 't3bs_accordion_item']]]],
|
||||
...
|
||||
);
|
||||
```
|
||||
|
||||
This automatically enforces the "tabs only contain tab items" / "accordions only contain
|
||||
accordion items" rules — editors can't accidentally drop a `textmedia` into an accordion's
|
||||
item slot. **Don't override this in PageTSconfig unless you have a deliberate reason.**
|
||||
|
||||
For a customer-specific column (e.g. "this colPos accepts only Hero or Card"), add the
|
||||
constraint in your customer extension's PageTSconfig:
|
||||
|
||||
```typoscript
|
||||
# local_packages/<customer>/site_<customer>/Configuration/page.tsconfig
|
||||
mod.web_layout.tt_content.colPos_list := addToList(2)
|
||||
mod.web_layout.BackendLayouts.HeroPage.config.backend_layout.rows.1.columns.1.allowed.CType = t3bootstrap_hero,t3bsCard
|
||||
```
|
||||
|
||||
## Migration Workflow
|
||||
|
||||
```
|
||||
1. Inventory the source.
|
||||
- WP: `wp post list`, screenshot blocks per post type
|
||||
- TYPO3: `SELECT CType, COUNT(*) FROM tt_content GROUP BY CType` (use claude-diagnostics' database:query)
|
||||
- Static: scrape the rendered pages, categorize by visual pattern
|
||||
2. Build the mapping table (use the decision matrix above).
|
||||
3. For flux_bs5_templates → ALWAYS the upgrade wizard. Don't re-do this work.
|
||||
4. For other sources, write the new content in the TYPO3 backend with the right CTypes,
|
||||
or script the import via a custom Symfony Command.
|
||||
5. After import: cache:flush, referenceindex:update, visually compare against the source.
|
||||
6. For each migrated CE, check: is the visual right? If not — is it a missing CE field
|
||||
(use the t3bootstrap-overrides skill for template tweaks) or a wrong CE choice
|
||||
(re-evaluate)?
|
||||
```
|
||||
|
||||
## Anti-Patterns
|
||||
|
||||
| Anti-pattern | Why it's bad | Correct approach |
|
||||
| --- | --- | --- |
|
||||
| Migrating all content as `html` CE | Loses TYPO3 semantics, FAL, link handling, accessibility | Use the decision matrix; `html` is the last resort, not the first |
|
||||
| Hand-migrating `flux_bs5_templates` content | Tedious, error-prone, breaks parent-child relations | Run the `t3bsContainerBs5MigrateFluxBs5` wizard |
|
||||
| Using `t3bs_container` for prose | Renders an empty Bootstrap container wrapper for no reason | Use `textmedia` directly; the page template already wraps it |
|
||||
| Stacking `t3bs_container` inside `t3bs_container` | Nested Bootstrap containers cause padding/margin compounding bugs | Use `t3bs_fluidrow` + `t3bs_column` to subdivide instead |
|
||||
| Placing `t3bs_buttonlink` inside a textmedia bodytext as RTE link | Looks like a button in the editor, won't get the Bootstrap classes | Use the `t3bs_buttonlink` CE next to the textmedia, or a `t3bs_buttongroup` if multiple |
|
||||
| Migrating a multi-image gallery as N separate `image` CEs | Loses the gallery's grid relationship | `wapplersystems/filecollection-gallery` set + `file_collection` CE |
|
||||
| Creating one `t3bs_card` per card in a 3-card grid | Each card is its own outer container | One `t3bs_cards` parent with three child content elements (one per card) — `tx_t3bs_cards_layout = grid-cards` for the grid |
|
||||
|
||||
## Reference Files in This Project
|
||||
|
||||
```text
|
||||
vendor/t3bootstrap/container-bs5-templates/Configuration/TCA/Overrides/tt_content.php # all t3bs_* registrations + ContainerConfiguration
|
||||
vendor/t3bootstrap/container-bs5-templates/Classes/Updates/MigrateFluxBs5ToContainerBs5.php # the upgrade wizard
|
||||
vendor/t3bootstrap/container-bs5-templates/Resources/Private/Templates/ # CE Fluid templates
|
||||
vendor/t3bootstrap/core/Configuration/TCA/Overrides/10_tt_content.php # extended tt_content fields (image_classes, element_classes, imagecols_grid, background_media)
|
||||
vendor/t3bootstrap/core/Configuration/TCA/Overrides/600_content_element_card.php # t3bsCard standalone
|
||||
vendor/t3bootstrap/core/Configuration/TCA/Overrides/600_content_element_compare_slider.php
|
||||
vendor/t3bootstrap/core/Configuration/TCA/Overrides/600_content_element_countdown.php
|
||||
vendor/t3bootstrap/core/Configuration/TCA/Overrides/202_content_element_counterbar.php
|
||||
vendor/t3bootstrap/hero-item/Configuration/TCA/Overrides/tt_content.php # Hero CType
|
||||
```
|
||||
|
||||
For overriding any of these CEs (different colors, additional fields, replaced templates),
|
||||
switch to the **`t3bootstrap-overrides`** skill.
|
||||
|
||||
For project bootstrapping (required composer packages, site sets), see the
|
||||
**`t3bootstrap-site-package`** skill.
|
||||
@@ -0,0 +1,4 @@
|
||||
interface:
|
||||
display_name: "T3Bootstrap Content Elements"
|
||||
short_description: "Pick the right CE when migrating content to T3Bootstrap"
|
||||
default_prompt: "Use $t3bootstrap-content-elements to choose which TYPO3 content element fits a piece of source content — the 23 t3bs_* container CEs, the custom single CEs (Card, CompareSlider, Countdown, Counterbar, Hero, Teaser, Testimonial), and the right CType-mapping for static HTML, WordPress blocks, Joomla modules, gridelements, dce, bootstrap_package, and the flux_bs5_templates → container_bs5_templates upgrade wizard."
|
||||
@@ -0,0 +1,519 @@
|
||||
---
|
||||
name: t3bootstrap-overrides
|
||||
description: Customize a T3Bootstrap-based TYPO3 v14 project minimally — without forking the upstream `t3bootstrap/*` packages. Covers the four override surfaces in order of invasiveness (Site Settings / TypoScript constants → SCSS `!default` variables → Fluid `templateRootPaths.10` overrides → custom DataProcessors), how to decide which surface fits a given change, the path-index conventions (`0` core, `5` core extensions, `10` site-package, `100` container-bs5, `200` Frameless), and the standard layout for a customer-specific extension that ships such overrides. Use this skill whenever the customer wants different colors, fonts, page structure, navigation, footer, content-element rendering, or any other deviation from upstream T3Bootstrap defaults.
|
||||
---
|
||||
|
||||
# T3Bootstrap Overrides
|
||||
|
||||
Use this skill when customizing a TYPO3 v14 project on the T3Bootstrap stack. The goal:
|
||||
**touch nothing in `vendor/`**, ship the customization as a thin customer extension, keep
|
||||
`composer update` upgrade-safe.
|
||||
|
||||
> **Companion skill:** [`t3bootstrap-site-package`](../t3bootstrap-site-package/SKILL.md) explains the underlying setup. Start there if the project isn't bootstrapped yet.
|
||||
|
||||
## Override Surfaces — Pick the Least Invasive
|
||||
|
||||
T3Bootstrap exposes **four layers** of customization. Always start with the highest layer
|
||||
that can solve the problem; descend only when forced.
|
||||
|
||||
```
|
||||
1. Site Settings / TypoScript constants ← most upgrade-safe, no code
|
||||
2. SCSS !default variable overrides ← brand colors, fonts, spacing tokens
|
||||
3. Fluid template overrides via index 10 ← structural HTML changes
|
||||
4. Custom DataProcessor / PHP ← only when data shape must change
|
||||
```
|
||||
|
||||
### Decision table
|
||||
|
||||
| Need | Layer | Example |
|
||||
| --- | --- | --- |
|
||||
| Change brand color | 2 (SCSS) or 1 (CSS custom property) | Re-define `$primary` |
|
||||
| Change header height / sticky behavior | 1 (constants) | `header.sticky` setting |
|
||||
| Show/hide language menu | 1 (constants) | `navigation.languageMenu` |
|
||||
| Different button styling | 1 + 2 | CSS custom property, or `$btn-padding-y` SCSS |
|
||||
| Add an extra CSS class to all CEs | 3 (override Content layout) | `Resources/Private/Layouts/Content/Default.html` |
|
||||
| Replace the Header partial with something completely different | 3 (override partial) | `Resources/Private/Partials/PageHeader.html` |
|
||||
| Change the data passed to a CE | 4 (custom DataProcessor) | Replace `FrameClassesProcessor` |
|
||||
|
||||
If a question is at the boundary (e.g. "is this an SCSS change or a Fluid override?"),
|
||||
the answer is usually: **whichever is closer to the top of the table**.
|
||||
|
||||
## Layer 1 — Site Settings / TypoScript Constants
|
||||
|
||||
The `t3bootstrap/template` set exposes a large set of constants under
|
||||
`Configuration/TypoScript/constants.typoscript`. Categories include navigation, language,
|
||||
text, font, search box, logo, banner, body tag, breadcrumb, color, color-mode, language
|
||||
defaults, screen, domains.
|
||||
|
||||
### Where they're defined
|
||||
|
||||
```text
|
||||
vendor/t3bootstrap/template/Configuration/TypoScript/constants.typoscript # the master file (~639 lines)
|
||||
vendor/t3bootstrap/template/Configuration/TypoScript/Plugin/Constants/*.typoscript # per-plugin (calendarize, indexedsearch, …)
|
||||
```
|
||||
|
||||
### How to override
|
||||
|
||||
#### Best — Site Setting in the TYPO3 v14 Backend
|
||||
Site Settings module → "T3Bootstrap Template" category → change the value. Persisted to
|
||||
`config/sites/<site>/settings.yaml` automatically. Reviewable in git.
|
||||
|
||||
#### Better — customer extension's Site Set
|
||||
Settings shipped from a customer extension's `Configuration/Sets/<Customer>/settings.yaml`:
|
||||
|
||||
```yaml
|
||||
# local_packages/<customer>/site_<customer>/Configuration/Sets/Site<Customer>/settings.yaml
|
||||
plugin.tx_template.view.templateRootPath: 'EXT:site_<customer>/Resources/Private/Templates/'
|
||||
plugin.tx_template.view.partialRootPath: 'EXT:site_<customer>/Resources/Private/Partials/'
|
||||
plugin.tx_template.view.layoutRootPath: 'EXT:site_<customer>/Resources/Private/Layouts/'
|
||||
|
||||
# Color tokens at the constants level (CSS custom property variables will see them)
|
||||
color.primary: '#005262'
|
||||
color.secondary: '#55aa63'
|
||||
```
|
||||
|
||||
#### Acceptable — TypoScript constants in a customer extension
|
||||
Only if you need conditions or includes that the Settings YAML can't express:
|
||||
|
||||
```typoscript
|
||||
# local_packages/<customer>/site_<customer>/Configuration/Sets/Site<Customer>/constants.typoscript
|
||||
plugin.tx_template.view.templateRootPath = EXT:site_<customer>/Resources/Private/Templates/
|
||||
```
|
||||
|
||||
> **Never** edit the upstream constants file. Any constant you want to change has a
|
||||
> matching site setting key — find it in the backend Constants Editor or in the master
|
||||
> constants file's `# cat=…` comments.
|
||||
|
||||
## Layer 2 — SCSS Variable Overrides
|
||||
|
||||
T3Bootstrap's SCSS is built around Bootstrap 5 and uses `!default` on every variable so
|
||||
customer SCSS loaded **before** the vendor file wins.
|
||||
|
||||
### The compilation pipeline
|
||||
|
||||
The stack relies on `wapplersystems/ws-scss` (or any project-set-up Node/Vite/PostCSS
|
||||
pipeline). The conventional entry point is one customer SCSS file that:
|
||||
|
||||
1. Defines overrides
|
||||
2. Imports the t3bootstrap base
|
||||
3. Imports Bootstrap 5
|
||||
4. Adds any extra component CSS
|
||||
|
||||
### Master variables file
|
||||
|
||||
```text
|
||||
vendor/t3bootstrap/template/Resources/Public/SCSS/_variables.scss
|
||||
```
|
||||
|
||||
Representative excerpt — **all values are `!default`, so you can re-set them upstream**:
|
||||
|
||||
```scss
|
||||
$primary: #005262 !default;
|
||||
$secondary: #55aa63 !default;
|
||||
$lightblue: #87c8e6 !default;
|
||||
|
||||
$prefix: bs- !default;
|
||||
|
||||
$custom-colors: (
|
||||
dark-gray: #005262,
|
||||
gray: #999,
|
||||
graylight: #f7f7f7
|
||||
) !default;
|
||||
|
||||
$icon-sizes: (
|
||||
sm: 2rem,
|
||||
md: 3rem,
|
||||
lg: 4rem,
|
||||
xl: 6rem
|
||||
) !default;
|
||||
|
||||
$font-family-sans-serif: 'Open Sans', "Helvetica Neue", Helvetica, Arial, sans-serif !default;
|
||||
$h1-font-size: 2.0rem !default;
|
||||
$h2-font-size: 1.8rem !default;
|
||||
$font-size-base: 0.95rem !default;
|
||||
```
|
||||
|
||||
Related files in the same directory: `_colors.scss`, `_mixins.scss`, `_mmenu.scss`,
|
||||
`_variables-dark.scss`, `_variables-contrast-high.scss`, and the subdirectories
|
||||
`additions/`, `aos/`, `aria/`, `base-layout/`, `bootstrap/`, `components/`, `effects/`,
|
||||
`elements/`, `extensions/`, `fonts/`, `mixins/`.
|
||||
|
||||
### Customer override pattern
|
||||
|
||||
```scss
|
||||
/* local_packages/<customer>/site_<customer>/Resources/Public/Scss/main.scss */
|
||||
|
||||
/* 1. Re-define variables BEFORE importing t3bootstrap */
|
||||
$primary: #c81d25;
|
||||
$secondary: #2b6cb0;
|
||||
$font-family-sans-serif: 'Inter', sans-serif;
|
||||
|
||||
$custom-colors: (
|
||||
brand-dark: #1a1a2e,
|
||||
brand-light: #f5f5f5,
|
||||
);
|
||||
|
||||
/* Bootstrap defaults can also be redefined here, BEFORE bootstrap loads */
|
||||
$btn-border-radius: 0;
|
||||
|
||||
/* 2. Import the t3bootstrap base — this brings in Bootstrap 5 and all defaults */
|
||||
@import 'EXT:template/Resources/Public/SCSS/base-layout';
|
||||
|
||||
/* 3. Project-specific additions */
|
||||
.c-customer-banner {
|
||||
background: $primary;
|
||||
/* … */
|
||||
}
|
||||
```
|
||||
|
||||
`@import 'EXT:template/...'` works inside `ws_scss` — it resolves `EXT:` paths via the
|
||||
TYPO3 path resolver. If your toolchain doesn't, use a relative or absolute path.
|
||||
|
||||
### When to use CSS custom properties instead
|
||||
|
||||
Bootstrap 5 ships **CSS custom properties** (`--bs-primary`, `--bs-body-color`, …) for
|
||||
runtime themability. T3Bootstrap respects them.
|
||||
|
||||
```css
|
||||
/* As an inline-style block on the page, or in a separate stylesheet loaded after Bootstrap */
|
||||
:root {
|
||||
--bs-primary: #c81d25;
|
||||
--bs-secondary: #2b6cb0;
|
||||
}
|
||||
```
|
||||
|
||||
**Rule of thumb:** values that must be available at runtime (dark mode, theme switching,
|
||||
editor-tweaked colors via Site Settings) → CSS custom properties. Values fixed at build
|
||||
time (font stack, spacing scale, breakpoints) → SCSS variables.
|
||||
|
||||
## Layer 3 — Fluid Template Overrides via Path Index
|
||||
|
||||
Every Fluid-rendering object in T3Bootstrap exposes `templateRootPaths`, `partialRootPaths`,
|
||||
and `layoutRootPaths` as numerically-indexed arrays. **Higher index wins.** The convention
|
||||
is:
|
||||
|
||||
| Index | Owner | Purpose |
|
||||
| --- | --- | --- |
|
||||
| `0` | t3bootstrap base | Original templates. Never touch. |
|
||||
| `5` | `t3bootstrap/core` extension overrides | E.g. core's `fluid_styled_content` overrides. |
|
||||
| `9` / `40` | `t3bootstrap/template` plugin-specific overrides | Felogin, fluid_styled_content, indexed_search etc. |
|
||||
| `10` | **Customer site package** | This is the slot you write to. |
|
||||
| `100` | `t3bootstrap/container-bs5-templates` | The `t3bs_*` CE templates. |
|
||||
| `200` | Frameless variant from `container-bs5-templates` | `Frameless/` layout dir for the "no-frame" CE option. |
|
||||
|
||||
### The page template's override hook
|
||||
|
||||
`vendor/t3bootstrap/template/Configuration/TypoScript/HTML/Page/body.typoscript` (lines
|
||||
77–90):
|
||||
|
||||
```typoscript
|
||||
layoutRootPaths {
|
||||
0 = EXT:template/Resources/Private/Layouts/
|
||||
10 = {$plugin.tx_template.view.layoutRootPath}
|
||||
}
|
||||
templateRootPaths {
|
||||
0 = EXT:template/Resources/Private/Templates/Page/
|
||||
10 = {$plugin.tx_template.view.templateRootPath}
|
||||
}
|
||||
partialRootPaths {
|
||||
0 = EXT:template/Resources/Private/Partials/
|
||||
10 = {$plugin.tx_template.view.partialRootPath}
|
||||
}
|
||||
```
|
||||
|
||||
Configure `plugin.tx_template.view.*` via Site Settings (preferred) or constants — see
|
||||
Layer 1.
|
||||
|
||||
### What's in `Resources/Private/Templates/Page/` upstream
|
||||
|
||||
```
|
||||
1Column.html
|
||||
2Columns.html
|
||||
2Columns2.html
|
||||
3Columns.html
|
||||
Onepager.html
|
||||
```
|
||||
|
||||
These are picked by the page's **backend layout**. Override one by copying it to
|
||||
`local_packages/<customer>/site_<customer>/Resources/Private/Templates/2Columns.html` and
|
||||
modifying.
|
||||
|
||||
### Layouts upstream
|
||||
|
||||
```
|
||||
Resources/Private/Layouts/
|
||||
├── Content.html # The wrapper used by all fluid_styled_content CEs
|
||||
└── Page.html # The HTML shell <html><body>…
|
||||
```
|
||||
|
||||
### Partials upstream — what's worth overriding
|
||||
|
||||
```
|
||||
Resources/Private/Partials/
|
||||
├── BackgroundMedia.html
|
||||
├── Footer/ ← whole footer block partials (columns, copyright bar)
|
||||
├── Header/ ← header column partials
|
||||
├── Navigation/ ← main nav, breadcrumb, language menu, mobile burger
|
||||
├── Hero.html
|
||||
├── Navigation.html
|
||||
├── PageFooter.html
|
||||
├── PageHeader.html
|
||||
├── Searchbox.html
|
||||
└── Skiplinks.html
|
||||
```
|
||||
|
||||
#### Common override targets
|
||||
|
||||
| Want to change | Override |
|
||||
| --- | --- |
|
||||
| Site-wide header structure | `Resources/Private/Partials/PageHeader.html` |
|
||||
| Logo placement, sticky behavior | `Resources/Private/Partials/Header/*.html` |
|
||||
| Navigation rendering | `Resources/Private/Partials/Navigation.html` + `Navigation/*.html` |
|
||||
| Search box markup | `Resources/Private/Partials/Searchbox.html` |
|
||||
| Footer layout | `Resources/Private/Partials/PageFooter.html` + `Footer/*.html` |
|
||||
| Skiplinks for a11y | `Resources/Private/Partials/Skiplinks.html` |
|
||||
| Hero markup | `Resources/Private/Partials/Hero.html` |
|
||||
| Background-media wrapper | `Resources/Private/Partials/BackgroundMedia.html` |
|
||||
|
||||
> Copy the **whole** partial, then modify. Fluid does not "merge" — once index 10
|
||||
> shadows index 0, it must contain the full template.
|
||||
|
||||
## Overriding `fluid_styled_content` CEs
|
||||
|
||||
The stack already overrides core's `fluid_styled_content` at index `9` (template) and `5`
|
||||
(layouts) via `t3bootstrap/core`. To override **further**, point to a higher index:
|
||||
|
||||
```typoscript
|
||||
# In a customer extension's setup.typoscript
|
||||
lib.contentElement.templateRootPaths.20 = EXT:site_<customer>/Resources/Private/ContentElements/Templates/
|
||||
lib.contentElement.partialRootPaths.20 = EXT:site_<customer>/Resources/Private/ContentElements/Partials/
|
||||
lib.contentElement.layoutRootPaths.20 = EXT:site_<customer>/Resources/Private/ContentElements/Layouts/
|
||||
```
|
||||
|
||||
Upstream-rendered CTypes you can override there:
|
||||
|
||||
```text
|
||||
vendor/t3bootstrap/core/Resources/Private/Extensions/fluid_styled_content/Templates/
|
||||
├── Textmedia.html
|
||||
├── Textpic.html
|
||||
├── Image.html
|
||||
├── Table.html
|
||||
├── Shortcut.html
|
||||
├── Card.html
|
||||
├── CardsCarousel.html
|
||||
├── Counterbar.html
|
||||
├── Countdown.html
|
||||
├── CompareSlider.html
|
||||
└── NumberCarousel.html
|
||||
```
|
||||
|
||||
For the `t3bs_*` container-based CEs use the **container_bs5_templates** path indices:
|
||||
|
||||
```typoscript
|
||||
# Override e.g. the Card.html template for t3bs_card
|
||||
lib.t3bsContent.templateRootPaths.200 = EXT:site_<customer>/Resources/Private/T3bsContent/Templates/
|
||||
lib.t3bsContent.partialRootPaths.200 = EXT:site_<customer>/Resources/Private/T3bsContent/Partials/
|
||||
```
|
||||
|
||||
Source:
|
||||
|
||||
```text
|
||||
vendor/t3bootstrap/container-bs5-templates/Resources/Private/Templates/
|
||||
├── Card.html ← t3bs_card
|
||||
├── Cards.html ← t3bs_cards
|
||||
├── Accordion.html ← t3bs_accordion
|
||||
├── AccordionItem.html
|
||||
├── Tabs.html
|
||||
├── TabItem.html
|
||||
├── Carousel.html
|
||||
├── CarouselItem.html
|
||||
├── Container.html
|
||||
├── FluidRow.html
|
||||
├── Column.html
|
||||
├── Alert.html
|
||||
├── Panel.html
|
||||
├── Well.html
|
||||
├── Thumbnail.html
|
||||
├── Media.html
|
||||
├── Example.html
|
||||
├── Timeline.html
|
||||
├── TimelineItem.html
|
||||
├── Buttongroup.html
|
||||
├── Buttonlink.html
|
||||
├── Megamenu.html
|
||||
└── MegamenuItem.html
|
||||
```
|
||||
|
||||
## Layer 4 — Custom DataProcessors
|
||||
|
||||
Only needed when you want to **change the data shape** the Fluid templates see, not just
|
||||
the markup. Examples:
|
||||
|
||||
- Add a derived field (e.g. a "read time" estimate for news items).
|
||||
- Replace `T3Bootstrap\Core\Frontend\DataProcessing\FrameClassesProcessor` with a custom one that emits different frame CSS classes.
|
||||
- Add a side-effect (logging, prefetching, conditional caching of related data).
|
||||
|
||||
Upstream processors used by `lib.t3bsContent`:
|
||||
|
||||
```text
|
||||
T3Bootstrap\Core\Frontend\DataProcessing\IconProcessor # 706
|
||||
T3Bootstrap\Core\Frontend\DataProcessing\FrameClassesProcessor # 707
|
||||
T3Bootstrap\Core\Frontend\DataProcessing\AosDataAttributeProcessor # 708
|
||||
T3Bootstrap\Core\Frontend\DataProcessing\ProcessedDataToRegisterProcessor # 900
|
||||
```
|
||||
|
||||
Plus core's `TYPO3\CMS\Frontend\DataProcessing\FilesProcessor` at 703 for `background_media`.
|
||||
|
||||
### Adding a custom processor
|
||||
|
||||
```typoscript
|
||||
# Customer Site Set setup.typoscript
|
||||
lib.t3bsContent.dataProcessing.950 = Vendor\SiteCustomer\DataProcessing\ReadTimeProcessor
|
||||
lib.t3bsContent.dataProcessing.950.target = readTime
|
||||
```
|
||||
|
||||
### Replacing an upstream processor
|
||||
|
||||
```typoscript
|
||||
# Replace at the same index — TypoScript merges shallow, so reassign:
|
||||
lib.t3bsContent.dataProcessing.707 = Vendor\SiteCustomer\DataProcessing\CustomFrameClassesProcessor
|
||||
lib.t3bsContent.dataProcessing.707 >
|
||||
lib.t3bsContent.dataProcessing.707 = Vendor\SiteCustomer\DataProcessing\CustomFrameClassesProcessor
|
||||
```
|
||||
|
||||
The `>` operator clears the original config sub-tree first to prevent stray options.
|
||||
|
||||
### TSFE-aware processors
|
||||
|
||||
On TYPO3 v14 there is no more `$GLOBALS['TSFE']`. T3Bootstrap's processors use the
|
||||
**`RegisterUtility`** static registry at `T3Bootstrap\Core\Utility\RegisterUtility` to
|
||||
share per-request state across processors and ViewHelpers. If your processor needs to
|
||||
publish a value for a later ViewHelper, write to that registry — don't reach for the
|
||||
removed TSFE register.
|
||||
|
||||
## Standard Customer-Extension Layout
|
||||
|
||||
```
|
||||
local_packages/<customer>/site_<customer>/
|
||||
├── composer.json
|
||||
├── ext_emconf.php
|
||||
├── ext_localconf.php
|
||||
├── Classes/
|
||||
│ ├── DataProcessing/ # Layer 4
|
||||
│ └── ViewHelpers/
|
||||
├── Configuration/
|
||||
│ ├── Sets/
|
||||
│ │ └── Site<Customer>/
|
||||
│ │ ├── config.yaml # dependencies
|
||||
│ │ ├── settings.yaml # Layer 1
|
||||
│ │ ├── constants.typoscript # Layer 1 (only if Settings YAML insufficient)
|
||||
│ │ └── setup.typoscript # Layer 3 path-index registration + Layer 4 processors
|
||||
│ └── TCA/Overrides/
|
||||
└── Resources/
|
||||
├── Private/
|
||||
│ ├── Templates/ # Page templates (Layer 3)
|
||||
│ ├── Layouts/ # Page + content layouts
|
||||
│ ├── Partials/ # Header/Footer/Nav/Hero/… (Layer 3)
|
||||
│ ├── ContentElements/ # fluid_styled_content overrides
|
||||
│ │ ├── Templates/
|
||||
│ │ ├── Layouts/
|
||||
│ │ └── Partials/
|
||||
│ ├── T3bsContent/ # t3bs_* CE overrides
|
||||
│ │ ├── Templates/
|
||||
│ │ └── Partials/
|
||||
│ └── Language/
|
||||
└── Public/
|
||||
├── Scss/
|
||||
│ ├── main.scss # Layer 2 — !default overrides + imports
|
||||
│ └── _customer-variables.scss
|
||||
├── Css/ # compiled output
|
||||
└── JavaScript/
|
||||
```
|
||||
|
||||
`Configuration/Sets/Site<Customer>/config.yaml`:
|
||||
|
||||
```yaml
|
||||
name: <customer>/site-<customer>
|
||||
label: <Customer> Site Customization
|
||||
dependencies:
|
||||
- t3bootstrap/template
|
||||
- t3bootstrap/container-bs5-templates
|
||||
```
|
||||
|
||||
`setup.typoscript`:
|
||||
|
||||
```typoscript
|
||||
# Page templates
|
||||
plugin.tx_template {
|
||||
view {
|
||||
templateRootPath = EXT:site_<customer>/Resources/Private/Templates/
|
||||
partialRootPath = EXT:site_<customer>/Resources/Private/Partials/
|
||||
layoutRootPath = EXT:site_<customer>/Resources/Private/Layouts/
|
||||
}
|
||||
}
|
||||
|
||||
# fluid_styled_content extensions
|
||||
lib.contentElement {
|
||||
templateRootPaths.20 = EXT:site_<customer>/Resources/Private/ContentElements/Templates/
|
||||
partialRootPaths.20 = EXT:site_<customer>/Resources/Private/ContentElements/Partials/
|
||||
layoutRootPaths.20 = EXT:site_<customer>/Resources/Private/ContentElements/Layouts/
|
||||
}
|
||||
|
||||
# t3bs_* CEs
|
||||
lib.t3bsContent {
|
||||
templateRootPaths.200 = EXT:site_<customer>/Resources/Private/T3bsContent/Templates/
|
||||
partialRootPaths.200 = EXT:site_<customer>/Resources/Private/T3bsContent/Partials/
|
||||
}
|
||||
|
||||
# Custom DataProcessor
|
||||
lib.t3bsContent.dataProcessing.950 = Vendor\SiteCustomer\DataProcessing\ReadTimeProcessor
|
||||
```
|
||||
|
||||
Then add the customer set to the site config:
|
||||
|
||||
```yaml
|
||||
# config/sites/<site-id>/config.yaml
|
||||
dependencies:
|
||||
- t3bootstrap/template
|
||||
- t3bootstrap/container-bs5-templates
|
||||
- <customer>/site-<customer> # <- new
|
||||
```
|
||||
|
||||
## Anti-Patterns
|
||||
|
||||
| Anti-pattern | Why it's bad | Correct approach |
|
||||
| --- | --- | --- |
|
||||
| Editing files under `vendor/t3bootstrap/*/` | Composer wipes changes on next update | Override via the customer extension's path index `10` (or higher) |
|
||||
| Forking `t3bootstrap/template` in customer's GitHub | Loses upstream fixes; merge conflicts forever | Customer extension + targeted partial overrides |
|
||||
| Adding raw `<style>` in PageTSconfig to "patch" colors | Fragile, gets purged by cache flushes, not visible at build time | Layer 2 (SCSS `!default`) or CSS custom properties |
|
||||
| Copying ALL upstream partials into the customer ext "just in case" | Now you own every change forever | Copy only what you override |
|
||||
| Setting `templateRootPaths.0` in the customer extension | Shadows the original; future upstream changes invisible | Use index `10` (or higher), keep `0` for vendor |
|
||||
| Cloning the whole vendor SCSS tree | Re-doing Bootstrap themability | Re-define `!default` variables in customer SCSS, import vendor base |
|
||||
| Hardcoding `EXT:template/...` paths in the customer ext templates | The customer extension shouldn't refer to upstream paths | Use Fluid layout/partial inheritance — `<f:layout name="Default"/>` finds it via `layoutRootPaths` automatically |
|
||||
| Modifying `lib.dynamicContent` "to add fields" | The DataProcessor pipeline is the right hook | Add a processor at index 900+ |
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
After any override change:
|
||||
|
||||
1. `ddev exec vendor/bin/typo3 cache:flush` — TypoScript and Fluid template paths are cached.
|
||||
2. Reload the frontend; if SCSS changed, run the customer's CSS build (`npm run build`, or `ws-scss` watcher).
|
||||
3. Inspect the rendered HTML — confirm your override is the one rendered (look for a distinctive marker comment you added).
|
||||
4. **TYPO3 backend → Maintenance → "Render TypoScript"** → confirm the right `templateRootPaths.10` / `.20` / `.200` are populated with your paths.
|
||||
5. If layered overrides don't seem to take effect: list `lib.t3bsContent.templateRootPaths` via `vendor/bin/typo3 ts:setup --path=lib.t3bsContent.templateRootPaths` (from `claude-diagnostics`) — index values shown in numeric order.
|
||||
|
||||
## Reference Files in This Project
|
||||
|
||||
```text
|
||||
vendor/t3bootstrap/template/Configuration/TypoScript/constants.typoscript # all constants
|
||||
vendor/t3bootstrap/template/Configuration/TypoScript/HTML/Page/body.typoscript # main layoutRootPaths block
|
||||
vendor/t3bootstrap/template/Resources/Public/SCSS/_variables.scss # SCSS variables
|
||||
vendor/t3bootstrap/template/Resources/Private/Partials/ # partials to override
|
||||
vendor/t3bootstrap/template/Resources/Private/Templates/Page/ # page templates
|
||||
vendor/t3bootstrap/core/Resources/Private/Extensions/fluid_styled_content/ # core CE overrides at index 5/9
|
||||
vendor/t3bootstrap/container-bs5-templates/Configuration/Sets/ContainerBs5Templates/setup.typoscript # lib.t3bsContent declaration
|
||||
vendor/t3bootstrap/container-bs5-templates/Resources/Private/Templates/ # t3bs_* CE templates
|
||||
```
|
||||
|
||||
For CE-by-CE migration mapping and the `t3bs_*` catalog, see the
|
||||
**`t3bootstrap-content-elements`** skill.
|
||||
@@ -0,0 +1,4 @@
|
||||
interface:
|
||||
display_name: "T3Bootstrap Overrides"
|
||||
short_description: "Customize T3Bootstrap minimally without forking upstream"
|
||||
default_prompt: "Use $t3bootstrap-overrides to customize a T3Bootstrap-based TYPO3 v14 project — pick the least invasive override surface (Site Settings, SCSS `!default`, Fluid `templateRootPaths.10`, or custom DataProcessor) for the change at hand and ship it from a thin customer extension instead of forking `vendor/t3bootstrap/*`."
|
||||
@@ -0,0 +1,402 @@
|
||||
---
|
||||
name: t3bootstrap-site-package
|
||||
description: Set up and configure a TYPO3 v14 project on the T3Bootstrap stack — composer repositories and dependencies for `t3bootstrap/*` and `wapplersystems/*` packages, site configuration with the right Site Sets, multi-language setup, when (and when not) to add a local site package, and the standard set of optional add-on packages (news, blog, address, sliders, gallery, hero, card, counter, countdown). Use this skill when bootstrapping a new T3Bootstrap project, adding a t3bootstrap add-on to an existing project, debugging "set not found" or unexpected content-element-missing errors, or deciding whether a customer-specific extension is needed.
|
||||
---
|
||||
|
||||
# T3Bootstrap Site Package
|
||||
|
||||
Use this skill when setting up or extending a TYPO3 v14 project that is built on the
|
||||
**T3Bootstrap** stack — i.e. uses `t3bootstrap/template`, `t3bootstrap/core` and the
|
||||
related WapplerSystems extensions instead of (or in addition to) a hand-rolled site
|
||||
package.
|
||||
|
||||
> **Companion skills:**
|
||||
> - [`t3bootstrap-overrides`](../t3bootstrap-overrides/SKILL.md) once setup is done and customer styling/templating begins.
|
||||
> - [`t3bootstrap-content-elements`](../t3bootstrap-content-elements/SKILL.md) for which CE to use where.
|
||||
|
||||
## First Checks
|
||||
|
||||
Before adding anything, **read what already exists**:
|
||||
|
||||
1. Is the project Composer mode? (`composer.json` at root, `vendor/` directory present.)
|
||||
2. Which `t3bootstrap/*` and `wapplersystems/*` packages are already required? — `composer show | grep -E "t3bootstrap|wapplersystems"`
|
||||
3. Where is the site config? — `config/sites/<site-id>/config.yaml`. Which sets does its `dependencies:` list?
|
||||
4. Is there a **local site package**? Look for `packages/<vendor>/`, `local_packages/`, or any in-repo TYPO3 extension. **On a vanilla T3Bootstrap project there usually is NO local site package** — the stack is sufficient out of the box and customization happens via Site Settings + Fluid overrides (see `t3bootstrap-overrides`).
|
||||
5. Is DDEV configured? — `.ddev/config.yaml` present. Confirm PHP version and the DB engine before suggesting commands.
|
||||
|
||||
## The Core Stack
|
||||
|
||||
A T3Bootstrap project always uses these three foundation extensions:
|
||||
|
||||
| Package | Role |
|
||||
| --- | --- |
|
||||
| `t3bootstrap/core` | Base ext: ViewHelpers, DataProcessors, BackendLayouts, extended `tt_content` fields (spacing, background, classes, breakpoint grid), `RegisterUtility` (TSFE-replacement registry on v14). |
|
||||
| `t3bootstrap/template` | Site template: page layouts, navigation, footer, search box, language menu, SCSS theme. Pulls Bootstrap 5 and the icon sets. |
|
||||
| `t3bootstrap/container-bs5-templates` | The 23 Bootstrap 5 content elements (Card, Accordion, Tabs, Carousel, Timeline, Grid Row/Col, Megamenu, Buttons, …). Replaces the legacy Flux-based `flux_bs5_templates`. |
|
||||
|
||||
These three are mandatory. Everything else is an add-on.
|
||||
|
||||
### Add-on Packages
|
||||
|
||||
All add-ons are optional; pull only what the project needs. Each ships its own Site Set
|
||||
that has to be included in the site config to take effect.
|
||||
|
||||
#### T3Bootstrap-vendored add-ons
|
||||
|
||||
| Package | Adds |
|
||||
| --- | --- |
|
||||
| `t3bootstrap/hero-item` | Hero content element (full-width banner with title, subtitle, CTA, background image/video). |
|
||||
| `t3bootstrap/t3bootstrap-news` | `georgringer/news` integration with T3Bootstrap-styled list/detail templates. |
|
||||
| `t3bootstrap/t3bootstrap-blog` | `t3g/blog` integration with T3Bootstrap-styled templates. |
|
||||
| `t3bootstrap/t3bootstrap-address` | Address record CE styled for the template. |
|
||||
| `t3bootstrap/t3bootstrap-form` | EXT:form templates and finishers wired into the template. |
|
||||
| `t3bootstrap/t3bootstrap-filecollection_gallery` | File-collection-driven gallery CE. |
|
||||
| `t3bootstrap/t3bootstrap-wsslider` | Slider integration for ws_slider. |
|
||||
| `t3bootstrap/template-fontawesomeicons` | Font Awesome icon set Site Set. |
|
||||
| `t3bootstrap/template-bootstrapicons` | Bootstrap Icons Site Set. |
|
||||
| `t3bootstrap/template-aos` | Animate-on-scroll Site Set. |
|
||||
| `t3bootstrap/template-imagedesigns` | Image design presets (rounded, framed, shadowed, …). |
|
||||
|
||||
#### WapplerSystems shared extensions
|
||||
|
||||
| Package | Adds |
|
||||
| --- | --- |
|
||||
| `wapplersystems/ws-scss` | SCSS-to-CSS compilation pipeline used by `t3bootstrap/template`. |
|
||||
| `wapplersystems/ws-components` | Modular SCSS/JS component system (`<scssComponents:require>` / `<jsComponents:require>`). |
|
||||
| `wapplersystems/ws-slider` | Generic slider framework (front-end-library-agnostic). |
|
||||
| `wapplersystems/font-downloader` | Self-host Google Fonts. |
|
||||
| `wapplersystems/teaser` | Teaser CE. |
|
||||
| `wapplersystems/videos` | Video CE. |
|
||||
| `wapplersystems/testimonials` | Testimonials CE. |
|
||||
| `wapplersystems/address` | Address plugin (news-variant). |
|
||||
| `wapplersystems/newslayouts` | Additional news layouts (3-col, 4-col, vertical list, top-image detail, …). |
|
||||
| `wapplersystems/tag` | Tagging system. |
|
||||
|
||||
## composer.json — The Repository Block
|
||||
|
||||
All T3Bootstrap packages are hosted on the **Gitea** instance at `git.wappler.systems`,
|
||||
WapplerSystems packages on **GitHub**. Both need explicit `repositories` entries in
|
||||
`composer.json` (Packagist does not mirror them).
|
||||
|
||||
```json
|
||||
{
|
||||
"repositories": [
|
||||
{ "type": "git", "url": "gitea@git.wappler.systems:T3Bootstrap/core.git" },
|
||||
{ "type": "git", "url": "gitea@git.wappler.systems:T3Bootstrap/template.git" },
|
||||
{ "type": "git", "url": "gitea@git.wappler.systems:T3Bootstrap/container-bs5-templates.git" },
|
||||
{ "type": "git", "url": "gitea@git.wappler.systems:T3Bootstrap/t3bootstrap-news.git" },
|
||||
{ "type": "git", "url": "gitea@git.wappler.systems:T3Bootstrap/t3bootstrap-blog.git" },
|
||||
{ "type": "git", "url": "gitea@git.wappler.systems:T3Bootstrap/t3bootstrap-address.git" },
|
||||
{ "type": "git", "url": "gitea@git.wappler.systems:T3Bootstrap/t3bootstrap-form.git" },
|
||||
{ "type": "git", "url": "gitea@git.wappler.systems:T3Bootstrap/t3bootstrap-heroitem.git" },
|
||||
{ "type": "git", "url": "gitea@git.wappler.systems:T3Bootstrap/t3bootstrap-filecollection_gallery.git" },
|
||||
{ "type": "git", "url": "gitea@git.wappler.systems:T3Bootstrap/t3bootstrap-wsslider.git" },
|
||||
{ "type": "git", "url": "git@github.com:WapplerSystems/ws_scss.git" },
|
||||
{ "type": "git", "url": "git@github.com:WapplerSystems/ws-components.git" },
|
||||
{ "type": "git", "url": "git@github.com:WapplerSystems/teaser.git" },
|
||||
{ "type": "git", "url": "git@github.com:WapplerSystems/videos.git" },
|
||||
{ "type": "git", "url": "git@github.com:WapplerSystems/testimonials.git" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### SSH access
|
||||
|
||||
The Gitea SSH URL requires the developer machine to be authorized at
|
||||
`git.wappler.systems`. Inside DDEV containers, run `ddev auth ssh` on the **host**
|
||||
beforehand so the agent forwards. HTTPS fallback URL pattern:
|
||||
`https://git.wappler.systems/T3Bootstrap/<repo>.git`.
|
||||
|
||||
### Require Block — Version Aliasing
|
||||
|
||||
The packages are typically tracked on the `release/v14` branch. Use `as`-aliases so
|
||||
Composer's solver treats the dev branch as a satisfiable version range:
|
||||
|
||||
```json
|
||||
{
|
||||
"require": {
|
||||
"typo3/cms-core": "^14.0",
|
||||
"t3bootstrap/core": "dev-release/v14 as 14.0.0",
|
||||
"t3bootstrap/template": "dev-release/v14 as 14.0.0",
|
||||
"t3bootstrap/container-bs5-templates": "dev-release/v14 as 14.0.0",
|
||||
"t3bootstrap/t3bootstrap-news": "dev-release/v14 as 14.0.0",
|
||||
"wapplersystems/ws-scss": "dev-master as 14.0.0",
|
||||
"wapplersystems/ws-components": "dev-master as 14.0.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> **Stability:** add `"minimum-stability": "dev"` and `"prefer-stable": true` at the
|
||||
> top level — otherwise Composer refuses dev branches.
|
||||
|
||||
## Site Sets — The Real Configuration Surface
|
||||
|
||||
T3Bootstrap configures itself via **TYPO3 v14 Site Sets**, not by patching TypoScript
|
||||
into the root template. Every t3bootstrap and wapplersystems extension ships one or more
|
||||
sets under `Configuration/Sets/<SetName>/config.yaml`.
|
||||
|
||||
### Set Catalog (foundation)
|
||||
|
||||
| Set | Provided by | Pulls in |
|
||||
| --- | --- | --- |
|
||||
| `t3bootstrap/core` | `t3bootstrap/core` | TypoScript constants & setup for the core registry, ViewHelpers, DataProcessors. |
|
||||
| `t3bootstrap/template` | `t3bootstrap/template` | Page rendering, layouts, navigation, footer; **depends on** `t3bootstrap/core`, `t3bootstrap/gridlayouts`, `typo3/indexed-search`. |
|
||||
| `t3bootstrap/container-bs5-templates` | `t3bootstrap/container-bs5-templates` | All 23 `t3bs_*` CTypes; depends on `t3bootstrap/core`. |
|
||||
| `t3bootstrap/gridlayouts` | `t3bootstrap/core` | Grid layouts for text/media elements (CE-internal column splits). |
|
||||
|
||||
### Set Catalog (icons / theming)
|
||||
|
||||
| Set | Provided by | Pulls in |
|
||||
| --- | --- | --- |
|
||||
| `t3bootstrap/template-fontawesomeicons` | `t3bootstrap/template` | Font Awesome assets and link to the icon picker. |
|
||||
| `t3bootstrap/template-bootstrapicons` | `t3bootstrap/template` | Bootstrap Icons assets. |
|
||||
| `t3bootstrap/template-aos` | `t3bootstrap/template` | animate-on-scroll JS + CSS. |
|
||||
| `t3bootstrap/template-imagedesigns` | `t3bootstrap/template` | Image design presets. |
|
||||
| `t3bootstrap/icons` | `t3bootstrap/core` | Generic icon registry hooks. |
|
||||
|
||||
### Set Catalog (CE add-ons)
|
||||
|
||||
| Set | Provided by |
|
||||
| --- | --- |
|
||||
| `t3bootstrap/card-element` | `t3bootstrap/core` |
|
||||
| `t3bootstrap/compareslider-element` | `t3bootstrap/core` |
|
||||
| `t3bootstrap/countdown-element` | `t3bootstrap/core` |
|
||||
| `t3bootstrap/counterbar-element` | `t3bootstrap/core` |
|
||||
| `t3bootstrap/hero-item` | `t3bootstrap/hero-item` |
|
||||
|
||||
### Set Catalog (news / blog / address / form / gallery)
|
||||
|
||||
| Set | Provided by |
|
||||
| --- | --- |
|
||||
| `t3bootstrap/news` | `t3bootstrap/t3bootstrap-news` |
|
||||
| `t3bootstrap/news-timeline-cards-straight` | `t3bootstrap/t3bootstrap-news` |
|
||||
| `t3bootstrap/news-timeline-cards-alternately` | `t3bootstrap/t3bootstrap-news` |
|
||||
| `t3bootstrap/news-newsblock` | `t3bootstrap/t3bootstrap-news` |
|
||||
| `t3bootstrap/news-background-image-latest` | `t3bootstrap/t3bootstrap-news` |
|
||||
| `t3bootstrap/news-right-image-latest` | `t3bootstrap/t3bootstrap-news` |
|
||||
| `wapplersystems/newslayouts` | `wapplersystems/newslayouts` |
|
||||
| `wapplersystems/newslayouts-detail-topimage` | `wapplersystems/newslayouts` |
|
||||
| `wapplersystems/newslayouts-list-3columns` | `wapplersystems/newslayouts` |
|
||||
| `wapplersystems/newslayouts-list-4columns` | `wapplersystems/newslayouts` |
|
||||
| `wapplersystems/newslayouts-list-vertical` | `wapplersystems/newslayouts` |
|
||||
| `t3bootstrap/blog` | `t3bootstrap/t3bootstrap-blog` |
|
||||
| `t3bootstrap/address` | `t3bootstrap/t3bootstrap-address` |
|
||||
| `wapplersystems/address-googlemaps` | `wapplersystems/address` |
|
||||
| `wapplersystems/address-openstreetmap` | `wapplersystems/address` |
|
||||
| `t3bootstrap/form` | `t3bootstrap/t3bootstrap-form` |
|
||||
| `wapplersystems/filecollection-gallery` | `t3bootstrap/t3bootstrap-filecollection_gallery` |
|
||||
| `wapplersystems/teaser` | `wapplersystems/teaser` |
|
||||
| `wapplersystems/testimonials` | `wapplersystems/testimonials` |
|
||||
|
||||
### Set Catalog (sliders)
|
||||
|
||||
| Set | Provided by |
|
||||
| --- | --- |
|
||||
| `wapplersystems/ws-slider` | `wapplersystems/ws-slider` |
|
||||
| `wapplersystems/ws-slider-flexslider` | `wapplersystems/ws-slider` |
|
||||
| `wapplersystems/ws-slider-tinyslider` | `wapplersystems/ws-slider` |
|
||||
| `wapplersystems/ws-slider-swiper` | `wapplersystems/ws-slider` |
|
||||
| `wapplersystems/ws-slider-bootstrap` | `wapplersystems/ws-slider` |
|
||||
| `wapplersystems/ws-slider-slick` | `wapplersystems/ws-slider` |
|
||||
| `t3bootstrap/ws-slider` | `t3bootstrap/t3bootstrap-wsslider` (T3Bootstrap-styled wrapper) |
|
||||
|
||||
> A package's **PHP code** is loaded once Composer pulls it in. Its **TypoScript and
|
||||
> settings**, however, only take effect when the matching **Site Set is listed in
|
||||
> `config/sites/<site-id>/config.yaml`** — adding the composer dependency without the
|
||||
> set means nothing renders.
|
||||
|
||||
## Site Config — Typical `config.yaml`
|
||||
|
||||
```yaml
|
||||
base: 'https://my-project.example.com/'
|
||||
rootPageId: 1
|
||||
websiteTitle: 'My Project'
|
||||
|
||||
dependencies:
|
||||
# foundation — order matters: core → template → CE library
|
||||
- t3bootstrap/template # depends on t3bootstrap/core + gridlayouts
|
||||
- t3bootstrap/container-bs5-templates
|
||||
|
||||
# icons & theme add-ons
|
||||
- t3bootstrap/template-fontawesomeicons
|
||||
- t3bootstrap/template-bootstrapicons
|
||||
- t3bootstrap/template-aos
|
||||
- t3bootstrap/template-imagedesigns
|
||||
|
||||
# CE add-ons (only what the project needs)
|
||||
- t3bootstrap/card-element
|
||||
- t3bootstrap/counterbar-element
|
||||
- t3bootstrap/countdown-element
|
||||
- t3bootstrap/compareslider-element
|
||||
- t3bootstrap/hero-item
|
||||
|
||||
# content domains (only what the project needs)
|
||||
- t3bootstrap/news
|
||||
- t3bootstrap/blog
|
||||
- t3bootstrap/address
|
||||
- t3bootstrap/form
|
||||
|
||||
# optional vendor add-ons
|
||||
- wapplersystems/teaser
|
||||
- wapplersystems/testimonials
|
||||
- wapplersystems/newslayouts
|
||||
- wapplersystems/ws-slider-swiper
|
||||
- wapplersystems/filecollection-gallery
|
||||
|
||||
# TYPO3 core sets
|
||||
- typo3/felogin
|
||||
- typo3/seo-sitemap
|
||||
|
||||
languages:
|
||||
- title: Deutsch
|
||||
enabled: true
|
||||
languageId: 0
|
||||
base: /de/
|
||||
locale: de_DE.utf8
|
||||
iso-639-1: de
|
||||
hreflang: de
|
||||
flag: de
|
||||
- title: English
|
||||
enabled: true
|
||||
languageId: 1
|
||||
base: /en/
|
||||
locale: en_US.utf8
|
||||
iso-639-1: en
|
||||
hreflang: en
|
||||
fallbackType: strict
|
||||
flag: en-us-gb
|
||||
|
||||
errorHandling:
|
||||
- errorCode: 404
|
||||
errorHandler: Page
|
||||
errorContentSource: 't3://page?uid=<404-page-uid>'
|
||||
- errorCode: 403
|
||||
errorHandler: Page
|
||||
errorContentSource: 't3://page?uid=<403-page-uid>'
|
||||
- errorCode: 500
|
||||
errorHandler: Page
|
||||
errorContentSource: 't3://page?uid=<500-page-uid>'
|
||||
|
||||
routes:
|
||||
- route: robots.txt
|
||||
type: staticText
|
||||
content: |
|
||||
User-agent: *
|
||||
Disallow: /typo3/
|
||||
Disallow: /typo3_src/
|
||||
Allow: /typo3/sysext/frontend/Resources/Public/*
|
||||
```
|
||||
|
||||
### Set Dependency Resolution
|
||||
|
||||
A set's `dependencies:` are resolved transitively — listing `t3bootstrap/template`
|
||||
automatically pulls in `t3bootstrap/core` and `t3bootstrap/gridlayouts`. You only need
|
||||
to list the *highest-level* set you want active.
|
||||
|
||||
But: **explicit beats transitive for clarity.** Listing the foundation sets explicitly
|
||||
makes the config self-documenting and avoids surprises when sets change their deps.
|
||||
|
||||
## Do You Need a Local Site Package?
|
||||
|
||||
The honest answer for most projects: **no**. The T3Bootstrap stack already provides
|
||||
everything a site package usually wraps:
|
||||
|
||||
| Site-package responsibility | Where it lives in the T3Bootstrap stack |
|
||||
| --- | --- |
|
||||
| Page rendering / Fluid layouts | `t3bootstrap/template` → override via `templateRootPaths.10` (see `t3bootstrap-overrides`) |
|
||||
| Content element templates | `t3bootstrap/container-bs5-templates` + `t3bootstrap/core` → override via root-paths |
|
||||
| Color theme | `_variables.scss` `!default` overrides (see `t3bootstrap-overrides`) |
|
||||
| Backend layouts | shipped by `t3bootstrap/template`, customer extends via PageTSconfig |
|
||||
| Routing | site config `routeEnhancers` |
|
||||
| Settings | site config `settings:` + site sets |
|
||||
|
||||
### When you DO need a local extension
|
||||
|
||||
Add a customer-specific extension only if **any** of these is true:
|
||||
|
||||
- **Custom PHP** — DataProcessors, Middlewares, EventListeners, ViewHelpers, RegisterUtility extensions, Scheduler tasks. PHP must live in a registered extension.
|
||||
- **Custom Fluid templates** that go beyond drop-in overrides — e.g. you want to ship reusable Partials for the customer's brand. (Even drop-in overrides work without an extension if you load them from `fileadmin/`, but that mixes content storage with code — not recommended.)
|
||||
- **Custom TCA** — fields on `tt_content` or other tables beyond what `t3bootstrap/core` already adds.
|
||||
- **Customer-specific Site Set** — settings, additional TypoScript, a backend layout shipped per project. Sets must live in `Configuration/Sets/<name>/config.yaml` of an extension.
|
||||
|
||||
### Skeleton for a customer extension
|
||||
|
||||
```text
|
||||
local_packages/<customer>/site_<customer>/
|
||||
├── composer.json
|
||||
├── ext_emconf.php
|
||||
├── Classes/
|
||||
│ ├── DataProcessing/
|
||||
│ └── ViewHelpers/
|
||||
├── Configuration/
|
||||
│ ├── Sets/
|
||||
│ │ └── Site<Customer>/
|
||||
│ │ ├── config.yaml
|
||||
│ │ ├── settings.yaml
|
||||
│ │ └── setup.typoscript
|
||||
│ └── TCA/Overrides/
|
||||
├── Resources/
|
||||
│ ├── Private/
|
||||
│ │ ├── Templates/ # site-package overrides (see t3bootstrap-overrides skill)
|
||||
│ │ ├── Partials/
|
||||
│ │ ├── Layouts/
|
||||
│ │ └── Language/
|
||||
│ └── Public/
|
||||
│ └── Scss/_overrides.scss # !default overrides
|
||||
└── ext_localconf.php
|
||||
```
|
||||
|
||||
Register the extension as a path repository in the root `composer.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"repositories": [
|
||||
{ "type": "path", "url": "local_packages/<customer>/site_<customer>" }
|
||||
],
|
||||
"require": {
|
||||
"<customer>/site-<customer>": "@dev"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then add `<customer>/site-<customer>` to the site config `dependencies:`.
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
| Symptom | Cause | Fix |
|
||||
| --- | --- | --- |
|
||||
| Backend shows no t3bs_* CEs | `t3bootstrap/container-bs5-templates` is required but its **Site Set is not listed** in `config/sites/<id>/config.yaml`. | Add `t3bootstrap/container-bs5-templates` to `dependencies:`. |
|
||||
| Frontend renders without styling | `t3bootstrap/template` set missing from `dependencies:`, or DDEV is serving stale CSS. | Verify set is listed, then `ddev exec vendor/bin/typo3 cache:flush` + recompile SCSS via `wapplersystems/ws-scss`. |
|
||||
| `Class "T3Bootstrap\Core\…" not found` | composer didn't pick up the package — usually missing `repositories` entry or no `dev-release/v14` `as` alias. | Re-check `composer.json`, run `composer require t3bootstrap/core:dev-release/v14`. |
|
||||
| `Set "t3bootstrap/news" not found` | the matching composer package (`t3bootstrap/t3bootstrap-news`) is not installed. | `composer require t3bootstrap/t3bootstrap-news`. |
|
||||
| News-extension styled wrong | `wapplersystems/newslayouts` listed before `t3bootstrap/news` so the t3bootstrap templates override the wapplersystems ones. | Order matters: T3Bootstrap-news set FIRST, then wapplersystems newslayouts add-ons. |
|
||||
| Permission prompt on Gitea SSH inside DDEV | DDEV agent isn't forwarded. | `ddev auth ssh` on host before `ddev composer install`. |
|
||||
|
||||
## Standard Setup Workflow
|
||||
|
||||
1. **Scaffold** with TYPO3 v14 distribution or a clean Composer install.
|
||||
2. **Add `claude-diagnostics`** (per global instructions) so the rest is faster to debug.
|
||||
3. **Add repositories block** to `composer.json` for the Gitea + GitHub URLs of t3bootstrap and wapplersystems packages.
|
||||
4. **Set stability:** `minimum-stability: dev`, `prefer-stable: true`.
|
||||
5. **Require the foundation:** `t3bootstrap/template`, `t3bootstrap/container-bs5-templates` — `t3bootstrap/core` comes transitively but list it explicitly if you want pinning.
|
||||
6. **Require add-ons** matching the project brief (news/blog/form/gallery/sliders).
|
||||
7. **Site config** — list the sets matching the requires; add languages, error handling, route enhancers.
|
||||
8. **Site Setting Module** in the TYPO3 backend → verify all sets resolved, no "set not found" errors.
|
||||
9. **Flush caches**, log in, place a "Card" content element to verify `t3bs_*` CTypes appear.
|
||||
10. **Decide on overrides** — switch to the `t3bootstrap-overrides` skill once the customer wants color/layout adjustments.
|
||||
|
||||
## Where to Find Things in the Vendor Tree
|
||||
|
||||
```text
|
||||
vendor/t3bootstrap/core/Configuration/Sets/ # Core sets (gridlayouts, icons, T3BCore)
|
||||
vendor/t3bootstrap/template/Configuration/Sets/Template/ # Main site template set
|
||||
vendor/t3bootstrap/template/Configuration/TypoScript/ # TypoScript constants + setup
|
||||
vendor/t3bootstrap/container-bs5-templates/Configuration/Sets/ContainerBs5Templates/
|
||||
vendor/t3bootstrap/container-bs5-templates/Classes/Updates/MigrateFluxBs5ToContainerBs5.php
|
||||
```
|
||||
|
||||
For the override surfaces (`templateRootPaths.10`, SCSS variables, …) see the
|
||||
**`t3bootstrap-overrides`** skill.
|
||||
|
||||
For the CE catalog and content-migration mapping see the
|
||||
**`t3bootstrap-content-elements`** skill.
|
||||
@@ -0,0 +1,4 @@
|
||||
interface:
|
||||
display_name: "T3Bootstrap Site Package"
|
||||
short_description: "Set up TYPO3 v14 projects on the T3Bootstrap stack"
|
||||
default_prompt: "Use $t3bootstrap-site-package to bootstrap or extend a TYPO3 v14 project built on the t3bootstrap/* and wapplersystems/* extensions — composer repositories, package selection, site sets, languages, route enhancers, and the question of when a local site-package extension is actually needed."
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/claude-code-marketplace.json",
|
||||
"name": "wapplersystems-t3bootstrap",
|
||||
"description": "T3Bootstrap-spezifische Agent Skills für Claude Code (Schwester-Marketplace zu wapplersystems/typo3-skills)",
|
||||
"owner": {
|
||||
"name": "WapplerSystems",
|
||||
"email": "info@wappler.systems"
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
"name": "t3bootstrap-skills",
|
||||
"source": "./",
|
||||
"description": "Skills für Setup, Override und Content-Migration auf dem T3Bootstrap-Stack (TYPO3 v14)",
|
||||
"category": "typo3",
|
||||
"tags": ["typo3", "t3bootstrap", "bootstrap5", "fluid", "ddev"]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
|
||||
"name": "t3bootstrap-skills",
|
||||
"version": "0.1.0",
|
||||
"description": "Agent Skills für das T3Bootstrap-Ökosystem (TYPO3 v14): Site-Package-Setup auf den t3bootstrap/*- und wapplersystems/*-Extensions, minimal-invasive Template- und CSS-Overrides, Content-Element-Auswahl und Inhalts-Migration auf die b13/container-basierten t3bs_*-CEs (inkl. Flux-bs5 → Container-bs5 Migration). Ergänzt das typo3-skills-Plugin um T3Bootstrap-spezifische Workflows.",
|
||||
"author": {
|
||||
"name": "WapplerSystems",
|
||||
"url": "https://wappler.systems"
|
||||
},
|
||||
"homepage": "https://git.wappler.systems/WapplerSystems/t3bootstrap-skills",
|
||||
"repository": "https://git.wappler.systems/WapplerSystems/t3bootstrap-skills",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"typo3",
|
||||
"typo3-v14",
|
||||
"t3bootstrap",
|
||||
"bootstrap5",
|
||||
"site-package",
|
||||
"content-elements",
|
||||
"container",
|
||||
"fluid",
|
||||
"ddev"
|
||||
],
|
||||
"skills": "./.agents/skills/"
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
# macOS metadata files
|
||||
.DS_Store
|
||||
._*
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
.fseventsd/
|
||||
Icon?
|
||||
|
||||
# IDE
|
||||
.idea/
|
||||
.vscode/
|
||||
|
||||
# OS
|
||||
Thumbs.db
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) WapplerSystems
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,75 @@
|
||||
# T3Bootstrap Skills
|
||||
|
||||
Agent Skills for working with the **T3Bootstrap** stack on TYPO3 v14 — the WapplerSystems
|
||||
ecosystem of `t3bootstrap/*` and `wapplersystems/*` extensions that delivers a Bootstrap 5
|
||||
based site template, content elements, and feature packages.
|
||||
|
||||
These skills teach an AI coding agent **what comes from the stack out of the box** and
|
||||
**how to extend it minimally** so that a customer project stays close to the upstream
|
||||
packages and remains upgrade-friendly.
|
||||
|
||||
> **Companion plugin:** [`wapplersystems/typo3-skills`](https://github.com/Starraider/typo3-skills)
|
||||
> covers generic TYPO3 v14 topics (Fluid patterns, Extbase, Content Blocks, CSP, Playwright,
|
||||
> …). The skills here are intentionally **T3Bootstrap-specific** and reference real
|
||||
> `t3bootstrap/*` package paths.
|
||||
|
||||
## Repository Layout
|
||||
|
||||
```
|
||||
.agents/skills/<skill-name>/
|
||||
├── SKILL.md # Skill definition (description + workflow)
|
||||
└── agents/openai.yaml # Standardized agent interface
|
||||
```
|
||||
|
||||
## Available Skills
|
||||
|
||||
| Skill | Purpose |
|
||||
| --- | --- |
|
||||
| [t3bootstrap-site-package](./.agents/skills/t3bootstrap-site-package/SKILL.md) | Set up a TYPO3 v14 project on the T3Bootstrap stack: `composer.json` repositories, the right `t3bootstrap/*` + `wapplersystems/*` packages, site sets in `config/sites/<site>/config.yaml`, when (and when not) to add a local site package, language configuration, route enhancers. |
|
||||
| [t3bootstrap-overrides](./.agents/skills/t3bootstrap-overrides/SKILL.md) | Minimal-invasive customization: Fluid template overrides via `templateRootPaths.10` / `partialRootPaths.10` / `layoutRootPaths.10`, SCSS variable overrides with `!default`, TypoScript constants, when to override what — without forking `t3bootstrap/template`. |
|
||||
| [t3bootstrap-content-elements](./.agents/skills/t3bootstrap-content-elements/SKILL.md) | Catalog of the 23 `t3bs_*` content elements from `t3bootstrap/container-bs5-templates`, decision matrix for content migration (static HTML, WordPress, Joomla, older TYPO3, Flux-bs5), and the `t3bsContainerBs5MigrateFluxBs5` upgrade wizard. |
|
||||
|
||||
## How Skills Are Invoked
|
||||
|
||||
Skills are auto-discovered by Claude Code from the `skills:` entry in `.claude-plugin/plugin.json`.
|
||||
Each skill's `SKILL.md` declares a description that triggers automatic invocation when the user's
|
||||
request matches.
|
||||
|
||||
Explicit invocation: mention the skill by name in a prompt
|
||||
(e.g. *"use the `t3bootstrap-content-elements` skill to map this WordPress accordion"*).
|
||||
|
||||
## Stack Versions This Plugin Targets
|
||||
|
||||
- TYPO3 **v14** (Composer mode)
|
||||
- `t3bootstrap/template` `dev-release/v14`
|
||||
- `t3bootstrap/core` `dev-release/v14`
|
||||
- `t3bootstrap/container-bs5-templates` `dev-release/v14`
|
||||
- Bootstrap **5**
|
||||
- PHP **8.3+** (PHP 8.5 on the reference project)
|
||||
- DDEV-based local dev
|
||||
|
||||
Skills assume TYPO3 v14. If a workflow differs on v13, the skill says so explicitly.
|
||||
|
||||
## Relation to the T3Bootstrap Page Builder
|
||||
|
||||
The reference project (`t3bootstrap14`) hosts a planned **Page Builder** inside
|
||||
`t3bootstrap/core`. The skills here describe the **current** template-and-content-element
|
||||
workflow. They will be revised as the builder lands and changes which configuration lives
|
||||
where (Site Settings YAML vs. TypoScript constants).
|
||||
|
||||
## Contributing
|
||||
|
||||
PRs welcome at `git.wappler.systems:WapplerSystems/t3bootstrap-skills`.
|
||||
|
||||
Conventions:
|
||||
|
||||
- **Real package paths.** Skills reference real `t3bootstrap/*` / `wapplersystems/*` paths
|
||||
rather than abstract placeholders — that *is* the topic. Customer site packages keep the
|
||||
`my-site-package` / `Vendor\MySitePackage\` placeholders used in `typo3-skills`.
|
||||
- **English content.** Frontmatter `description` and SKILL.md body in English. German
|
||||
inline labels (e.g. backend field labels) are quoted verbatim from the upstream packages.
|
||||
- **One SKILL.md per topic, deep but scannable.** Tables, file paths, code blocks. Avoid prose.
|
||||
|
||||
## License
|
||||
|
||||
[MIT](./LICENCE).
|
||||
Reference in New Issue
Block a user