The search JSON gains tab support: the new `filter` GET parameter
restricts results to one document type (product, news, download, story,
page, market); the response carries `filter` (active value or null) and
`facets.type` with per-type counts and active flags. Counts stay
complete while a filter is active (keepAllFacetsOnSelection), so tabs
never collapse - except on an empty filtered result, documented in spec
v1.12 clause 7.16.
The parameter is named `filter` because `type` is TYPO3's reserved
page-type parameter and crashes page resolution; like q and page it is
excluded from cHash validation. Facets come from EXT:solr's native
faceting, serialized generically by SearchJsonRenderer - a future
category facet only needs TypoScript.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
| **Applies to** | `evomedien/vitec` on TYPO3 v14.3 (headless) |
| **Applies to** | `evomedien/vitec` on TYPO3 v14.3 (headless) |
| **Owner** | evomedien — VITEC relaunch |
| **Owner** | evomedien — VITEC relaunch |
@@ -24,6 +24,8 @@
| 1.8 | 2026‑08‑13 | **Defect fix and interface change (additive).** Content Blocks never carried the Core *Appearance* tab: `layout`, `frame_class` — including the VITEC frame classes — `space_before_class`, `space_after_class`, `sectionIndex` and `linkToTop` were unreachable for editors on all nine blocks. Added centrally for every `vitec_*` type (7.7); the `appearance` envelope is unchanged, its values were merely always default. Side effect: those six columns now also appear raw inside `data` on top‑level blocks (B‑13), and `appearance.layout` is represented differently on the two envelope paths (B‑14). `intro-paragraph` gained `background_color` (7.7). `vitec_eventlist` gained the layout `regions`, emitting a `regions` array built from the region categories below parent 104; the event payload is specified for the first time (7.14). B‑11 and B‑12 recorded as resolved. |
| 1.8 | 2026‑08‑13 | **Defect fix and interface change (additive).** Content Blocks never carried the Core *Appearance* tab: `layout`, `frame_class` — including the VITEC frame classes — `space_before_class`, `space_after_class`, `sectionIndex` and `linkToTop` were unreachable for editors on all nine blocks. Added centrally for every `vitec_*` type (7.7); the `appearance` envelope is unchanged, its values were merely always default. Side effect: those six columns now also appear raw inside `data` on top‑level blocks (B‑13), and `appearance.layout` is represented differently on the two envelope paths (B‑14). `intro-paragraph` gained `background_color` (7.7). `vitec_eventlist` gained the layout `regions`, emitting a `regions` array built from the region categories below parent 104; the event payload is specified for the first time (7.14). B‑11 and B‑12 recorded as resolved. |
| 1.9 | 2026‑08‑15 | **Interface change, partly breaking.** The four list plugins were unified: every one of them now emits an object carrying `layout`, the new `showToolbar` flag and its payload array. `vitec_usecaselist` and `vitec_productlist` previously emitted a **bare array** — front ends reading them have to move one level down (7.3, 7.14, 8). New plugin **`vitec_solutionlist`** (`SolutionListJsonRenderer`, key `solutions`), the counterpart 7.13.2 had been asking for since v1.2. `tx_vitec_domain_model_usecase` gained `detail_page`, emitted as the resolved `detailUrl` in the story card shape and therefore also in the `vitec_modelcard` story branch, which had carried no link at all until now. Noted: `vitec_productlist` had a configurable `layout` that was never serialised, and its vocabulary (`0`–`3`) differs from the other lists. |
| 1.9 | 2026‑08‑15 | **Interface change, partly breaking.** The four list plugins were unified: every one of them now emits an object carrying `layout`, the new `showToolbar` flag and its payload array. `vitec_usecaselist` and `vitec_productlist` previously emitted a **bare array** — front ends reading them have to move one level down (7.3, 7.14, 8). New plugin **`vitec_solutionlist`** (`SolutionListJsonRenderer`, key `solutions`), the counterpart 7.13.2 had been asking for since v1.2. `tx_vitec_domain_model_usecase` gained `detail_page`, emitted as the resolved `detailUrl` in the story card shape and therefore also in the `vitec_modelcard` story branch, which had carried no link at all until now. Noted: `vitec_productlist` had a configurable `layout` that was never serialised, and its vocabulary (`0`–`3`) differs from the other lists. |
| 1.10 | 2026‑08‑18 | **Interface change (additive).**`tx_vitec_domain_model_product` gained five fields: `heroimage` (multiple FAL images, detail payload only), the richtext fields `description2`, `capabilities` and `textrelatedproducts`, and `portfolio` (TCA `link`) — emitted as a **resolved URL** through the new `LinkResolver::typolinkUrl()`. The product payloads are specified for the first time (7.15). Links in `contentelement` / `contentelementcta` that point at a **container** now resolve its children (`items`, page‑level shape) and `background` (7.4). Two record link handlers (`download`, `product`) added to the link browser, resolved server‑side per the new Clause 9.12; new middleware `vitec/download-file` streams `/download/file/<uid>` as a forced download (5.3), file lookup consolidated into `DownloadFileResolver` — first step towards the B‑4 target (10.2). Backend‑only: `relatedprodukt` moved from the Misc tab to General. Editorial: the document footer had been stuck at v1.7 since v1.8. |
| 1.10 | 2026‑08‑18 | **Interface change (additive).**`tx_vitec_domain_model_product` gained five fields: `heroimage` (multiple FAL images, detail payload only), the richtext fields `description2`, `capabilities` and `textrelatedproducts`, and `portfolio` (TCA `link`) — emitted as a **resolved URL** through the new `LinkResolver::typolinkUrl()`. The product payloads are specified for the first time (7.15). Links in `contentelement` / `contentelementcta` that point at a **container** now resolve its children (`items`, page‑level shape) and `background` (7.4). Two record link handlers (`download`, `product`) added to the link browser, resolved server‑side per the new Clause 9.12; new middleware `vitec/download-file` streams `/download/file/<uid>` as a forced download (5.3), file lookup consolidated into `DownloadFileResolver` — first step towards the B‑4 target (10.2). Backend‑only: `relatedprodukt` moved from the Misc tab to General. Editorial: the document footer had been stuck at v1.7 since v1.8. |
| 1.11 | 2026‑08‑21 | **New interface: site search.** Apache Solr 10 (dedicated VPS behind an HTTPS reverse proxy) with `apache-solr-for-typo3/solr` 14.0.0-RC1. The EXT:solr results plugin `solr_pi_results` on the search page is rendered headless by `SearchJsonRenderer` (payload key `search`) - request/response contract in the new Clause 7.16. Indexed corpus: pages plus product, market (`detail_page` only), use-case, news and download records; result `type` vocabulary `page\|product\|market\|story\|news\|download`. Downloads gained the canonical route `/download/<slug>` (uid route kept for the record links) and `private_download` is now enforced by `DownloadFileResolver` (5.3, 9.12). The VITEC Set now declares the solr set as a dependency - overriding a foreign set’s TypoScript requires loading after it (5.2). Editorial: the header table had been stuck at v1.9 since v1.10. |
| 1.12 | 2026‑08‑24 | **Interface change (additive).** The search endpoint (7.16) gained a type filter and facet counts: request parameter `filter` (a value from the `type` vocabulary; the natural name `type` is unavailable - it is TYPO3’s reserved page-type parameter), response keys `filter` (active filter or null) and `facets.type` (per-type document counts with `active` flags; counts stay complete while a filter is active, except when the filtered result is empty). Editorial baseline of 76 managed synonyms imported into `core_en` (codecs, acquired-brand names such as `exterity => avedia`, UK/US spellings, common misspellings) - synonyms apply at query time, no re-index. |
This document is drafted in the style of, and adopts the terminology conventions of,
This document is drafted in the style of, and adopts the terminology conventions of,
ISO/IEC/IEEE 42010 (architecture description), ISO/IEC/IEEE 26514 (information for
ISO/IEC/IEEE 42010 (architecture description), ISO/IEC/IEEE 26514 (information for
@@ -153,10 +155,13 @@ they normalise a raw `tt_content` row into an envelope and resolve nested elemen
| `georgringer/news` | ^14.0 | News records and plugins |
| `georgringer/news` | ^14.0 | News records and plugins |
| `apache-solr-for-typo3/solr` | 14.0.0-RC1 | Site search: indexing pipeline, query API |
| Apache Solr | 10.0.0 (dedicated VPS) | Search server, reached via an HTTPS reverse proxy |
| `evomedien/vitec` | ^1.0 | This project’s custom extension |
| `evomedien/vitec` | ^1.0 | This project’s custom extension |
> **NOTE** `friendsoftypo3/headless` is pinned to a **release candidate** (`^5.0@rc`).
> **NOTE** `friendsoftypo3/headless` is pinned to a **release candidate** (`^5.0@rc`).
> This is an upgrade‑sensitivity point; see 10.4.
> This is an upgrade‑sensitivity point; see 10.4. The same applies to
> `apache-solr-for-typo3/solr`, pinned to `14.0.0-RC1` (the only line for TYPO3 14).
### 5.2 Site configuration
### 5.2 Site configuration
The headless mode is activated in `config/sites/vitec/config.yaml`:
The headless mode is activated in `config/sites/vitec/config.yaml`:
@@ -175,7 +180,9 @@ dependencies:
The Site **Sets** listed under `dependencies` load, in order, the headless TypoScript
The Site **Sets** listed under `dependencies` load, in order, the headless TypoScript
base, the mixed‑mode overrides, the Content Blocks JSON integration and the News
base, the mixed‑mode overrides, the Content Blocks JSON integration and the News
integration. The VITEC Set (`EXT:vitec/Configuration/Sets/Vitecset`) layers the custom
integration. The VITEC Set (`EXT:vitec/Configuration/Sets/Vitecset`) layers the custom
definitions on top. The headless page response carries
definitions on top; it declares `apache-solr-for-typo3/solr` as a set dependency so
the solr defaults load **before** the VITEC overrides - sets load in dependency
order, and a set loaded later silently wins. The headless page response carries
`Content-Type: application/json; charset=utf-8`. Slug routing is configured with route
`Content-Type: application/json; charset=utf-8`. Slug routing is configured with route
enhancers for products (`tx_vitec_domain_model_product.slug`) and news detail
enhancers for products (`tx_vitec_domain_model_product.slug`) and news detail
(`path_segment`).
(`path_segment`).
@@ -189,7 +196,7 @@ that is, **before page resolution**:
|---|---|
|---|---|
| `vitec/form-submission` | Answers `POST /api/vitec/form/<formKey>` (Clause 7.8.2). Every other request passes through untouched. |
| `vitec/form-submission` | Answers `POST /api/vitec/form/<formKey>` (Clause 7.8.2). Every other request passes through untouched. |
| `vitec/success-story-path-rewrite` | Rewrites `/success-stories/<slug>` internally to `/success-stories/story/<slug>` when `<slug>` matches a visible Success Story. The page router would otherwise always resolve the public SEO URL to the list page (longest page‑slug prefix), so the detail subpage could never answer it. The browser URL is unchanged; a non‑matching slug leaves the request untouched; any exception leaves the request untouched. |
| `vitec/success-story-path-rewrite` | Rewrites `/success-stories/<slug>` internally to `/success-stories/story/<slug>` when `<slug>` matches a visible Success Story. The page router would otherwise always resolve the public SEO URL to the list page (longest page‑slug prefix), so the detail subpage could never answer it. The browser URL is unchanged; a non‑matching slug leaves the request untouched; any exception leaves the request untouched. |
| `vitec/download-file` | Answers `GET /download/file/<uid>`: resolves the download record's file (`DownloadFileResolver`: FAL → Collateral naming convention → `filepath`) and streams it with `Content-Disposition: attachment` (Clause 9.12). Unknown uid, hidden record or missing file fall through to normal page resolution. |
| `vitec/download-file` | Answers `GET /download/<slug>` (canonical; used by search results) and `GET /download/file/<uid>` (legacy; the download record links build this form): resolves the download record’s file (`DownloadFileResolver`: FAL → Collateral naming convention → `filepath`) and streams it with `Content-Disposition: attachment` (Clause 9.12). Records flagged `private_download` are refused. Unknown uid/slug, hidden or private record or missing file fall through to normal page resolution. |
### 5.4 Architectural principles (rationale)
### 5.4 Architectural principles (rationale)
- **P1 — One envelope.** Every content element, regardless of source, is exposed with
- **P1 — One envelope.** Every content element, regardless of source, is exposed with
@@ -897,6 +904,84 @@ rarely shows. The `layout` vocabulary remains `0`–`3` (see the v1.9 note).
---
---
### 7.16 Search payload (`solr_pi_results`)
The site search runs on Apache Solr through EXT:solr. The EXT:solr results plugin
`solr_pi_results` sits on the dedicated search page (`/search`) and is rendered
headless by `SearchJsonRenderer` under the payload key `search`. The renderer runs
EXT:solr’s own query pipeline (`SearchRequestBuilder` → `SearchResultSetService`) -
only the rendering differs from the stock Fluid plugin.
**Request.** GET parameters on the search page:
| Parameter | Meaning |
|---|---|
| `q` | Search terms. Absent or empty: the response keeps its full shape with `numFound: 0`, so the front end never needs a second code path. |
| `page` | 1-based result page, optional. |
| `filter` | Restrict results to one type from the `type` vocabulary below (e.g. `filter=product`). Unknown values are ignored. Named `filter` because `type` is TYPO3’s reserved page-type parameter. |
The EXT:solr namespace (`tx_solr[q]`, `tx_solr[page]`) is accepted as a fallback.
All three parameters are excluded from cHash validation; the search page is never
served from the page cache (the renderer disables caching per request - cached
variants would collide because excluded parameters do not enter the cache
| `download` | `/download/file/<uid>` | forced‑download endpoint (5.3); the canonical public form is `/download/<slug>` - both routes share `DownloadFileResolver`, which refuses `private_download` records |
---
---
@@ -1264,4 +1350,4 @@ remediation.
- Header convention — the uniform header section across CEs, plugins and containers.
- Header convention — the uniform header section across CEs, plugins and containers.
-`Configuration/Sets/Vitecset/setup.typoscript` — the single TypoScript entry point.
-`Configuration/Sets/Vitecset/setup.typoscript` — the single TypoScript entry point.
| `vitec:import-news` | Import old-site news records from `migrations/news_export.json` |
| `vitec:import-news` | Import old-site news records from `migrations/news_export.json` |
| `vitec:solr-index` | Work the Solr index queue from the CLI (`--initialize`, `--debug` single-stepping) - EXT:solr 14 ships no console commands of its own |
All commands support `--dry-run` and are safe to re-run.
All import/migration commands support `--dry-run` and are safe to re-run;
`vitec:solr-index` has no dry-run (indexing is idempotent anyway).
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.