Files
VITEC-website/packages/vitec
khaccount eae40f4286 Success-story migration + new plugins + JSON/UX polish
- Success Stories: full migration from old site (48/48, audited),
  markets n:n, quotation content block, columns content block,
  pretty SEO detail URLs via SuccessStoryPathRewrite middleware,
  list/detail split (list page 4 / story page), detailUrl/backUrl
- New plugins: VITEC Locations (grid/list/map + RTE map text),
  VITEC Customer Logos (color/bw logic, only-show-selected),
  VITEC Card (one plugin for product/story/market/solution
  with reloading FlexForm + custom backend preview renderer)
- Eventlist: layout dropdown (list/grid/teaserbar) in settings
- Hero section CB: Images/Video tabs, background video + overlay
- Product JSON: full category rootline (parents), fixed missing
  ConnectionPool import (all-products crash), category tree map
- Backend preview CSS: container-query responsive (narrow columns)
- Docs: ISO architecture spec, root + extension READMEs

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 09:53:33 +02:00
..
2026-07-09 10:10:05 +02:00
2026-05-18 14:46:25 +02:00
2026-05-18 14:46:25 +02:00
2026-07-09 10:19:45 +02:00

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 PHP Mode Content Blocks License Status


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

  • 🧩 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 toplevel page content and as children inside layout containers.
  • 🎛️ Editorfriendly Content Blocks — hero, cards, CTA, FAQ, video, intro and a twocolumn layout block, all with a unified header section.
  • 🔎 SEO built in — a schema.org @graph (Organization, Product, FAQ, Events, News …) is emitted per page.
  • 🛡️ Failsoft — 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.<key> (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 toplevel use plus a renderForRecord(array $row) for reuse inside containers — and delegates serialisation to a service (see UsecaseSerializer as the reference).

📖 The full, normative architecture & interface specification lives in 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/ShowJsonRendererUsecaseSerializer 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 Fullwidth hero with background image/video, overlays and CTA
card Flexible card (image/icon, CTAs, many layout variants)
cta-banner Calltoaction 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 Twocolumn layout (50/50 · 66/33 · 33/66) with peritem content

Layout containers

Nested column grids (b13/container) that own child content elements and emit them as items, with percolumn flex (align/justify) and a wholegrid 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 (JSONLD)

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

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/<site>/config.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. SerializerClasses/Service/<Domain>Serializer with serializeListItem() / serializeDetail().
  3. RendererClasses/UserFunc/<Domain><Kind>JsonRenderer with #[AsAllowedCallable] render() + renderForRecord(), delegating to the serializer.
  4. TypoScript — in Configuration/Sets/Vitecset/setup.typoscript:
    tt_content.<ctype> < lib.contentElementWithHeader
    tt_content.<ctype>.fields.content.fields.<key> = USER
    tt_content.<ctype>.fields.content.fields.<key>.userFunc = Evomedien\Vitec\UserFunc\<Class>->render
    
  5. Nesting — if it may sit inside a container, register it in PLUGIN_RENDERERS (in both ContentElementResolver and ContainerChildrenProcessor).
  6. Deploydatabase:updateschema "*.add,*.change" & cache:flush.

Conventions: list keys are plural, detail keys singular; pageid 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 Authoritative architecture & JSON interface specification (ISOstyle)
Documentation/HeadlessIntegration.md Informal stepbystep howto

License

GPL2.0orlater — © evomedien.

Built for the VITEC relaunch · TYPO3 headless + React