diff --git a/packages/vitec/README.md b/packages/vitec/README.md new file mode 100755 index 0000000..ae8d4ea --- /dev/null +++ b/packages/vitec/README.md @@ -0,0 +1,234 @@ +
+ +# VITEC + +### Headless TYPO3 extension powering the VITEC website + +The editorial backend of a decoupled platform: TYPO3 v14 authors the content, +this extension turns every content element into clean **JSON** for a React front end. + +
+ +![TYPO3](https://img.shields.io/badge/TYPO3-14.3-FF8700?logo=typo3&logoColor=white) +![PHP](https://img.shields.io/badge/PHP-8.x-777BB4?logo=php&logoColor=white) +![Mode](https://img.shields.io/badge/mode-headless_JSON-0A3D62) +![Content Blocks](https://img.shields.io/badge/Content_Blocks-v2-2ea44f) +![License](https://img.shields.io/badge/license-GPL--2.0--or--later-blue) +![Status](https://img.shields.io/badge/status-active_development-yellow) + +
+ +--- + +> **What is this?** +> `evomedien/vitec` is the custom TYPO3 extension behind the VITEC relaunch. The site +> runs **headless**: TYPO3 does not render HTML — it emits a JSON document per page that +> a separate React front end consumes. This extension provides the domain models, +> content elements, layout containers and the renderers that produce that JSON, plus +> schema.org structured data for SEO. + +## Table of contents + +- [Highlights](#highlights) +- [Architecture at a glance](#architecture-at-a-glance) +- [Content elements & plugins](#content-elements--plugins) +- [Content Blocks](#content-blocks) +- [Layout containers](#layout-containers) +- [Structured data (JSON‑LD)](#structured-data-json-ld) +- [Requirements](#requirements) +- [Installation](#installation) +- [Adding a new headless plugin](#adding-a-new-headless-plugin) +- [Project structure](#project-structure) +- [Documentation](#documentation) +- [License](#license) + +## Highlights + +- 🧩 **One JSON envelope for everything** — every content element, plugin, container and + Content Block is exposed with the same predictable outer shape. +- ⚡ **Pure JSON output** — domain payloads are built in PHP, fully decoupled from + TypoScript and templates, so the logic is testable and versionable. +- 🏗️ **Nestable by design** — plugins render both as top‑level page content and as + children inside layout containers. +- 🎛️ **Editor‑friendly Content Blocks** — hero, cards, CTA, FAQ, video, intro and a + two‑column layout block, all with a unified header section. +- 🔎 **SEO built in** — a schema.org `@graph` (Organization, Product, FAQ, Events, + News …) is emitted per page. +- 🛡️ **Fail‑soft** — a failing element yields empty output, never a broken page. + +## Architecture at a glance + +``` +HTTP request (headless: 1) + │ + ▼ +[L1] Page renderer friendsoftypo3/headless → { meta, content[], jsonLd } + │ + ▼ +[L2] Content-element envelope lib.contentElement(WithHeader) → id, type, appearance, content{header…} + │ + ▼ +[L3] Payload injection Classes/UserFunc/*JsonRenderer → content. (products, news, …) + │ + ▼ +[L4] Layout containers vitec_cols_* = JSON → items[].contentElements[] + │ + ▼ +[L5] Normalisation & nesting ContentElementResolver / ContainerChildrenProcessor + │ + ▼ +[L6] Structured data PageJsonLdRenderer + StructuredDataService → @graph +``` + +Each renderer follows one pattern — an `#[AsAllowedCallable] render()` for top‑level use +plus a `renderForRecord(array $row)` for reuse inside containers — and delegates +serialisation to a service (see [`UsecaseSerializer`](Classes/Service/UsecaseSerializer.php) +as the reference). + +> 📖 The full, normative architecture & interface specification lives in +> **[`Documentation/Headless-JSON-Architecture.md`](Documentation/Headless-JSON-Architecture.md)**. + +## Content elements & plugins + +| Domain | CType | Renderer | JSON key | +|---|---|---|---| +| Products | `vitec_productlist` / `vitec_productshow` | `ProductList/ProductShowJsonRenderer` | `products` / `product` | +| Success Stories | `vitec_usecaselist` / `vitec_usecaseshow` | `UsecaseList/ShowJsonRenderer` → `UsecaseSerializer` | `usecases` / `usecase` | +| Markets | `vitec_marketshow` | `MarketShowJsonRenderer` | `market` | +| Solutions | `vitec_solutionshow` | `SolutionShowJsonRenderer` | `solution` | +| Downloads | `vitec_downloadcard` / `vitec_downloadcardcollection` | `Downloadcard*JsonRenderer` | `downloadcard` / `downloadcardcollection` | +| Datasheets | `vitec_datasheets` | `DatasheetsJsonRenderer` | `datasheets` | +| Events | `vitec_eventlist` | `EventlistJsonRenderer` | `eventlist` | +| News | `news_pi1` (+ variants) | `NewsJsonRenderer` | `news` | + +## Content Blocks + +Declarative content elements (`friendsoftypo3/content-blocks`), serialised to JSON by +`nb-headless-content-blocks`. All share the unified **header section**. + +| Block | Purpose | +|---|---| +| `hero-section` | Full‑width hero with background image/video, overlays and CTA | +| `card` | Flexible card (image/icon, CTAs, many layout variants) | +| `cta-banner` | Call‑to‑action banner | +| `intro-paragraph` | Rich intro text with optional media | +| `video` | YouTube or uploaded video with poster | +| `faq` | Accordion; also feeds the `FAQPage` structured data | +| `columns` | Two‑column layout (50/50 · 66/33 · 33/66) with per‑item content | + +## Layout containers + +Nested column grids (`b13/container`) that own child content elements and emit them as +`items`, with per‑column flex (`align`/`justify`) and a whole‑grid `gap`. + +| CType | Layout | +|---|---| +| `vitec_cols_50_50` | Two equal columns | +| `vitec_cols_66_33` / `vitec_cols_33_66` | Asymmetric two columns | +| `vitec_cols_33_33_33` | Three columns | +| `vitec_cols_25_25_25_25` | Four columns | +| `vitec_container` | Single column with a custom CSS class | +| `vitec_cards_carousel` | Carousel of card elements | + +## Structured data (JSON‑LD) + +`PageJsonLdRenderer` + `StructuredDataService` assemble a schema.org `@graph` per page: +`Organization`, `WebSite` (root only), `BreadcrumbList`, `Product`, `VideoObject`, +`FAQPage`, `ExhibitionEvent` and `NewsArticle`. + +## Requirements + +| Component | Version | +|---|---| +| TYPO3 CMS | `^14.3` | +| PHP | `8.x` | +| `friendsoftypo3/headless` | `^5.0` | +| `friendsoftypo3/content-blocks` | `^2.4` | +| `netzbewegung/nb-headless-content-blocks` | `^0.0.23` | +| `b13/container` | `^3.1` | +| `georgringer/news` | `^14.0` | + +## Installation + +```bash +composer require evomedien/vitec + +# apply database schema and clear caches +vendor/bin/typo3 database:updateschema "*.add,*.change" +vendor/bin/typo3 cache:flush +``` + +Enable headless mode in the site configuration (`config/sites//config.yaml`): + +```yaml +headless: 1 +dependencies: + - friendsoftypo3/headless + - friendsoftypo3/headless-mixed + - nb-headless-content-blocks/headless-content-blocks + - georgringer/news +``` + +## Adding a new headless plugin + +The short version (full normative rules in the architecture spec, Clause 9 & Annex A): + +1. **Model / TCA / SQL** — create the domain table; declare table & field names as constants. +2. **Serializer** — `Classes/Service/Serializer` with `serializeListItem()` / `serializeDetail()`. +3. **Renderer** — `Classes/UserFunc/JsonRenderer` with + `#[AsAllowedCallable] render()` + `renderForRecord()`, delegating to the serializer. +4. **TypoScript** — in `Configuration/Sets/Vitecset/setup.typoscript`: + ```typoscript + tt_content. < lib.contentElementWithHeader + tt_content..fields.content.fields. = USER + tt_content..fields.content.fields..userFunc = Evomedien\Vitec\UserFunc\->render + ``` +5. **Nesting** — if it may sit inside a container, register it in `PLUGIN_RENDERERS` + (in both `ContentElementResolver` and `ContainerChildrenProcessor`). +6. **Deploy** — `database:updateschema "*.add,*.change"` & `cache:flush`. + +> **Conventions:** list keys are plural, detail keys singular; page‑id via the +> `frontend.page.information` request attribute; container CTypes derive with `<` (copy), +> never `=<`. + +## Project structure + +
+packages/vitec/ — click to expand + +``` +packages/vitec/ +├── Classes/ +│ ├── UserFunc/ # JSON renderers (one per plugin) — headless entry points +│ ├── Service/ # Serializers, ContentElementResolver, StructuredDataService +│ ├── DataProcessing/ # ContainerChildrenProcessor (container → items) +│ ├── Domain/Model|Repository/ +│ ├── Controller/ # Extbase controllers (non-headless / backend) +│ └── Backend/ · View/ · Hook/ · EventListener/ +├── ContentBlocks/ +│ └── ContentElements/ # card, cta-banner, columns, faq, hero-section, intro-paragraph, video +├── Configuration/ +│ ├── Sets/Vitecset/ # setup.typoscript — the single headless entry point +│ ├── TypoScript/Headless/ # containers, menus, news JSON definitions +│ ├── TCA/ · FlexForms/ · Services.yaml +├── Documentation/ +│ ├── Headless-JSON-Architecture.md # normative spec (start here) +│ └── HeadlessIntegration.md # informal how-to +├── Resources/ +└── ext_tables.sql · ext_localconf.php · composer.json +``` + +
+ +## Documentation + +| Document | Purpose | +|---|---| +| [`Documentation/Headless-JSON-Architecture.md`](Documentation/Headless-JSON-Architecture.md) | **Authoritative** architecture & JSON interface specification (ISO‑style) | +| [`Documentation/HeadlessIntegration.md`](Documentation/HeadlessIntegration.md) | Informal step‑by‑step how‑to | + +## License + +[GPL‑2.0‑or‑later](https://www.gnu.org/licenses/gpl-2.0.html) — © evomedien. + +
Built for the VITEC relaunch · TYPO3 headless + React