- Page-tree entries get a "Page tree display" field (columns | rail |
rail-compact), emitted as display + cardSize: Markets and Solutions
show their main pages as a list and the sub-pages as image cards on
hover. Page-tree items carry image (page media) and teaser (abstract)
from stage 2. Additive; front ends ignoring display render columns.
- vitec:attach-page-media gains --depth=2 and falls back to the page's
hero background before the grey placeholder; the 39 sub-solution
pages got their hero image as page media.
- MegamenuJsonRenderer tags every page carrying the menu with the menu
tables and tt_content_<uid>, so saving menu records refreshes all
pages instead of waiting for a full flush.
- Products catalog: drop catalog.news; both promo boxes ("Product
highlight", "Product news") are the entry's editorial teaser cards.
ProvideInsightsSpotlight back to its previous state.
- Spec v1.29 and v1.30 (header version corrected), README.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rebuild the product section after the agency sitemap and menu prototype
of 2026-11-02:
- vitec:build-product-overviews builds sysfolder labels (3 categories,
9 groups) below /products with 20 overview pages /products/<slug>
(layout 9: hero, intro per group, product cards, contact CTA) and two
menu shortcuts. Dry-run by default, idempotent, explicit sorting.
- ProvideProductCatalog reads that page tree and emits catalog version 2:
categories[].groups[].items[] of type page (productCount, products,
image) or shortcut (target indices), plus viewAll, news and search.
- Transitional v1 fields (groups[].products/link/uid, categories[].uid/
link, product teaser) keep the deployed front end alive; it read the
v1 shape and rendered a white page without them. Remove once the
front end reads items.
- ProvideInsightsSpotlight::latestNews() is public with a count.
- Product type-ahead (type 7385) adds matching overview pages and a
per-product overview with its menu path.
- Spec v1.28.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The Resources Section Layout select gained a third value, hardware
("Layout 3 - Hardware option"): Technical Highlights spread over two
columns, no resource cards
- ProductShowJsonRenderer::resourcesBand() emits the same envelope with
items: [] for hardware even when cards are maintained, so the cards
stay on the product and reappear when switching back to layout 1 or 2
- Spec v1.27 (resources.sectionLayout values)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- customer change request (2026-10-26): Resources = Downloads, the
detail band is simplified - capabilities leave the section, Technical
Highlights move left, the resource cards into the right column
(frontend already built on dev.vitec.com)
- TCA: capabilities, datasheets and downloads moved to the Misc tab -
parked, not removed; their JSON keys are unchanged. The planned
automatic newest-datasheet/documentation cards stay deferred by
request (the download route already serves the newest file per
Collateral convention, so the foundation is there)
- new resources_layout select on the Resources tab, English label and
description: Layout 1 = 50-50 (default, highlights left / cards
right), Layout 2 = 33-33-33 (highlights over two columns, cards in
the third); ext_tables.sql column added
- the manual resource card restype vocabulary gains Datasheet and
Brochure (select items plus icon picker seeds, no code change - the
renderer passes restype through as type): an editor can pin a single
datasheet card by linking the download record, which stays current
because the download route always serves the newest file
- ProductShowJsonRenderer: the resources envelope gains sectionLayout
('50-50'|'33-33-33'); verified live - Diamond-H delivers 33-33-33,
untouched products the 50-50 default, layout/items unchanged
- spec bumped to v1.26 (additive revision row, field table 7.15.1),
mirrored; frontend briefing notes the new key
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Structure per the agency agreement (Joe/Christina, confirmed 2026-10-23):
/markets -> eleven market hero pages -> their sub-market pages; the
use-case level stays sections on the sub-market pages.
- new vitec:align-market-pages: renames 8 main market pages onto the
agency names (slug change -> EXT:redirects), creates the 3 new markets,
hides the dropped "Security & Surveillance" (records/stories
untouched), reports unknown children. A child-slug pass realigns every
child to <parent-slug>/<slugified-title> (DataHandler does not cascade
slug changes; this also repaired the third embedded-slash slug,
rtcc-/-rtic). --publish unhides the tree (dev convenience; element
shells stay hidden)
- sub-market import: all 24 agency workbooks applied (4 existing pages,
20 created) - their Meta sheets were clones of Corporate Environments
(record_uid 32) and were repaired beforehand (market/sub-market set,
record_uid 0; the record taxonomy alignment is a separate step)
- SubmarketWorkbookImporter: page-properties parity (og/twitter titles
and descriptions, canonical, abstract from the intro copy) and a
placeholder upgrade pass - pages created in the same run only get the
generic grey (their uid is still NEW), the re-run swaps it for the
numbered per-page placeholder
- new market hero pipeline: frontend layout 23 "Market Hero Page"
(zones hero=colPos1, main=colPos0), Import\MarketHeroPageImporter +
vitec:import-market-hero-workbooks (inbox migrations/markethero_xlsx_in,
gitignored). Hero H1 travels on the introparagraph header (markethero
has no headline field), the hero CTA anchors #submarkets, sub-market
cards link their child page via t3://page, customerlogos and
usecaselist ship hidden until filled editorially, prefooter ctabanner;
full page-properties set with 11 curated keyword sets
- applied end to end and live-verified (layout 23 heroes with linked
cards, layout 21 sub pages with all six colPos groups, clean slugs)
- spec v1.25
Open: market RECORD taxonomy (story badges / Solr facets still use the
old 9 mains), featured product "ISR Video Mission Commander" has no
record, the /markets main page workbook (template 2) is a separate flow.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- new frontend layout 22 "Solution Group Page" (provider LAYOUT_MAP,
TCA layout item, locallang_pages.xlf; zones hero=colPos1, main=colPos0
like layout 5 so the front end reuses its components)
- new pipeline Import\SolutionGroupPageImporter +
vitec:import-solution-group-workbooks (inbox
migrations/solutiongroups_xlsx_in/, gitignored): reads the agency
"Template 06" group workbooks by column-A label scan, resolves the
group via "Hero H1" -> is_group record -> detail_page (pages must
exist), cursor-based slotNext() allows repeated CTypes per column
- element plan per page: markethero (+#capabilities CTA anchor) + hero
intro paragraph; intro + supporting 50/50; challenges header + 4
text_only cards; capabilities header + 4 alternating horizontal cards
(bullets as <ul>); usecaselist shipped HIDDEN (an empty selection
would list ALL stories - editors pick, then unhide); marketinsights;
prefooter ctabanner. Page properties as on the sub-solution pages,
8 curated keyword sets
- 56 numbered grey placeholders for pages 459-466 (7 slots per page)
- applied to all 8 group pages, live-verified on 459/465; the solutions
branch is now content-complete (groups + 39 details)
- spec v1.24 (revision row, head/footer)
Found on the way: the "Engagament" typo lives in page 465's title AND
slug; the record is spelled correctly. Fix needs coordination with the
sub-solution workbook metas - own task, not done here.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Joe's 39 "- Completed" workbooks applied to all 39 sub-solution pages
(#467-#515); both workbook inboxes are now gitignored and the tracked
test workbooks untracked - filled deliveries live in the Nextcloud
- new Import\ProductFamilyAliases: the workbooks reference product
FAMILIES in the product slots; 11 labels map to a representative
product, consulted by BOTH importers after the exact title match and
reported as "-> family alias"
- flip-card icons: dummy SVGs fileadmin/icons/flow/<name>.svg for Joe's
10-name vocabulary, attached by the new attachIconFile() through the
shared idempotent attachFalFile() (extracted from attachUrlFile);
real icons later REPLACE those files in the Filelist (same sys_file
uid), every card follows without a re-import
- image slots: numbered grey placeholders per page and slot
(fileadmin/placeholders/pages/<pid>-NN.png, the id rendered into the
image; generic grey as fallback). An existing reference is never
overwritten; a real URL on re-import swaps the placeholder away
- page properties per sub-solution: og/twitter title + description
mirror the SEO fields, canonical_link points at the page itself,
abstract derived from the intro copy (~300 chars, word boundary),
keywords from the curated PAGE_KEYWORDS set
- spec head-matter fix rides along (version table was stuck at 1.21,
real state 1.23)
Open afterwards: 3 missing Datapath stories + re-apply, quotes on 16
story records (list to Joe), slug slash on page 467.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- evo_megamenu_json stays project-neutral: new panel layout "catalog";
for such entries the MenuBuilder dispatches the new PSR-14 event
BuildCatalogEvent and emits whatever a listener sets as `catalog`
(null without a listener). The entry's teaser cards serve as the
featured tiles; the teaser inline field now also shows for "catalog",
and the entry form reloads when the layout changes. README section
"Layout catalog"
- VITEC listener ProvideProductCatalog fills it, modelled on the Ross
Video products menu: main categories below the "Product" root, their
subcategories as groups, products with a plain-text one-line teaser;
same visibility rules as the product list, Product Finder links
(/products?cat=&subcat=), empty categories and groups left out, three
queries for the whole catalog
- Product type-ahead GET /_json/?type=7385&q= (USER_INT page type,
ProductMenuSearchJsonRenderer): Solr restricted to products, last term
completed as a prefix, up to six product cards plus their titles as
autocomplete suggestions; endpoint announced in catalog.search
- Spec v1.23 (clause 7.16: product type-ahead)
- New record type tx_vitec_domain_model_searchcard ("best bets"):
keyword list, priority, optional referenced record (page, product,
story, solution, market, news) and overridable title/teaser/image/link;
hidden/start/end time allow timed campaigns
- SearchCardService delivers content.search.cards on page 1: max. 3,
priority-ordered, deduplicated by URL, independent of filter, facets
and result count. Keywords match as whole words/phrases, case- and
punctuation-insensitive, including one level of the Solr managed
synonyms in both directions (cached for an hour, fail-soft). Record
cards read the record's indexed Solr document, so a card always
matches the record's own search result
- Index fallback for markets and solutions: when the record carries no
image or text, the document takes the intro image (then the hero
background) and the hero subline, intro headline and intro text from
the content blocks of its detail page - selected by CType, so it works
for layout 21 and layout 5 alike; improves results and cards
- Fix: a search request without q returned an empty body instead of the
documented empty shape (stdClass resolved inside the renderer namespace)
- migrations/check_solution_fields.php: shows live/workspace versions of
solution records
- Spec v1.22 (clause 7.16: cards)
- Index the text columns of the market/solution Content Blocks and the
vitec_items/vitec_faq_items collection children; story documents now
include their body (inline tt_content children via
tx_vitec_usecase_content, same per-element extraction as pages) -
stories were indexed with subtitle and teaser only until now
- Upgrade EXT:solr 14.0.0-RC1 -> 14.0.2 final (the Solr image moved to a
fresh volume because the configset changed; synonyms restored via REST)
- News decay with age by publication date: crdate is the import date, so
news map datetime to created; boost function gated to news only
- Results carry `image`: processed 640px tile image per type,
root-relative, null for pages and downloads
- Spec v1.21: 7.16 states the /_json prefix and lists `solution` in the
type vocabulary; footer had been stuck at v1.19
- suggest-demo.html fetches through /_json after the URL swap
the customer workflow in mind: the customer fills one XLSX per sub-market,
an importer builds the page).
- Frontend layout 21 'Sub-Market Page' in the existing
BackendLayoutDataProvider: six zones, one per Figma section, emitted as
colPos110..colPos160 - the JSON groups plus appearance.layout are the
front-end contract (spec clause 7.17). A first attempt via page-TSconfig
BackendLayouts was the wrong mechanism next to the provider and was
removed again
- New Content Blocks vitec_markethero, vitec_marketintro,
vitec_marketinsights (field bags, serialized unprefixed under data);
the workflow section reuses intro-paragraph + vitec_card flip cards
- Stories gained quote/quote_person/quote_role (Testimonial tab),
maintained once per story, emitted on every story card; usecaselist
gained the layout value 'testimonials'
- New plugin vitec_productfeature: one referenced product as a full
product card, serialisation shared with the product list (cObj made
protected for the subclass)
- vitec_productlist gained hand-picked product selection: exactly the
chosen products in the editor's order, category filter ignored,
visibility filters kept - closes the long-standing single-select gap
- New CLI vitec:generate-submarket-workbooks: one protected customer
XLSX per sub-market (9 main markets, 25 sub-markets from the Market
category tree) - dropdowns filled live from the database, named ranges
as the importer contract, hidden Meta sheet pinning submarket/group/
record uid, soft character-limit warnings, asset URL fields
Verified end to end on Broadcast & Media: layout-21 payload with colPos110
carrying the hero element and its subline. Spec raised to v1.20.
- layout_variant gains the value "flipcard" (onChange: reload)
- "Card Back" palette in the Layout tab directly below layout_variant:
back_headline (Text, max 100) and back_text (Textarea, richtext),
displayCond-gated on the flipcard layout; serialised unconditionally -
the frontend keys the back face on layout_variant, not on field
presence (spec 7.7)
- backend preview: flipcard badge + back-headline line
- repair "[ Missing label ]" in the card selects: layout_variant /
background_variant are columns SHARED with vitec_ctabanner, and the
index-wise Content Blocks merge dropped four card-only values from
the base item list. Overrides/tt_content.php now pins the base column
to the cta-banner lists and hands vitec_card its full lists via
columnsOverrides (respected by FormEngine and DataHandler; an items
override can only extend, never shorten - array_replace_recursive)
- spec v1.19 incl. head-matter fix (version table was stuck at 1.17)
Server follow-up: database:updateschema "*.add,*.change" + cache:flush
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two work packages, one deploy.
Workbook field mapping completed (2026-09-18)
- highlights <- g:Technical Highlight (new spec-row component of the
full agency delivery; composeGroup() is generic, no change needed)
- applications <- g:Why Choose Card (benefit cards as one block)
- seometa <- new composed source x:seometa (Introduction body trimmed
at a word boundary to ~155 chars - the SEO sheet ships no meta
description, a trimmed intro beats an empty tag)
- teaser stays the hero one-liner, settling the varchar(255) question
- fix: "Save mapping" now merges over the stored mapping instead of
overwriting it - an empty dropdown no longer wipes a stored selector
Product model: solutions relation and Resources tab (2026-09-24)
- closes the gaps the full workbook walkthrough exposed (rows the
import deliberately skips because the model had no place for them)
- solutions: MM multi select to tx_vitec_domain_model_solution
(tx_vitec_product_solution_mm, relatedprodukt pattern), emitted by
both product renderers as solution cards in the shared shape
- Resources tab: inline child table tx_vitec_product_resource - per
entry a type (documentation/support), an editable card title/text,
an icon (free text with a value-picker seed set) and one link
(page/url/file/record via the link wizard). Deliberately no Extbase
model: only the UserFunc path reads the rows.
- datasheets: own MM selection of download records below the resource
list (tx_vitec_product_datasheet_mm); emitted into the SAME
resources envelope as ready-made type=datasheet cards (title/teaser/
icon from the record, url = the public /download/<slug> route, uid
fallback - private/hidden downloads 404 as everywhere)
- JSON `resources` (detail payload only, like heroimage): list envelope
{layout, items[]}; a hand-written card whose link is empty or
unresolvable is not emitted; layout switches to carousel above three
cards in total
- solutions hybrid (same day, after analysing all 100 workbooks: their
Solution Cards reference the 8 GROUPS in 98% of cases): new is_group
flag on the solution model, new idempotent CLI
vitec:create-solution-groups (8 group records; title source is
AlignSolutionsCommand::TARGET - now public -, category = the group's
own category, detail_page = the /solutions group page with -N
disambiguation). Group records are invisible to the solution list
and to vitec:align-solutions and only selectable in the product
relation; product solution cards carry isGroup
- spec raised to v1.18 (7.15 member table, 7.13.3 note, revision row;
the footer had been stuck at v1.15 since 1.16/1.17)
Requires on the server:
vendor/bin/typo3 database:updateschema "*.add,*.change"
vendor/bin/typo3 cache:flush
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two work packages, one deploy.
Workbook field mapping completed (2026-09-18)
- highlights <- g:Technical Highlight (new spec-row component of the
full agency delivery; composeGroup() is generic, no change needed)
- applications <- g:Why Choose Card (benefit cards as one block)
- seometa <- new composed source x:seometa (Introduction body trimmed
at a word boundary to ~155 chars - the SEO sheet ships no meta
description, a trimmed intro beats an empty tag)
- teaser stays the hero one-liner, settling the varchar(255) question
- fix: "Save mapping" now merges over the stored mapping instead of
overwriting it - an empty dropdown no longer wipes a stored selector
Product model: solutions relation and Resources tab (2026-09-24)
- closes the gaps the full workbook walkthrough exposed (rows the
import deliberately skips because the model had no place for them)
- solutions: MM multi select to tx_vitec_domain_model_solution
(tx_vitec_product_solution_mm, relatedprodukt pattern), emitted by
both product renderers as solution cards in the shared shape
- Resources tab: inline child table tx_vitec_product_resource - per
entry a type (documentation/support/datasheet), editable card title
and text, an icon (free text with a value-picker seed set) and one
link (page/url/file/record via the link wizard, so the Download tab
works too). Deliberately no Extbase model: only the UserFunc path
reads the rows.
- JSON `resources` (detail payload only, like heroimage): list envelope
{layout, items[]}; a card whose link is empty or unresolvable is not
emitted; layout switches to carousel above three cards
- spec raised to v1.18 (7.15 member table, revision row; the footer had
been stuck at v1.15 since 1.16/1.17)
Requires on the server:
vendor/bin/typo3 database:updateschema "*.add,*.change"
vendor/bin/typo3 cache:flush
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
sys_category gains a story selection and a layout (Options tab, alongside
the images field EXT:news puts there), so one editorial decision serves
every product list that renders the category. ProductListJsonRenderer emits
them beside the products in the 7.3 list envelope; each card carries
forCategories - the product categories it came from - so the front end hides
it with the same ?cat=/?subcat= filter it applies to the products. Stories
are collected over the category and its descendants and deduplicated.
Story links follow the existing rule (detail page's parent path plus slug,
which SuccessStoryPathRewrite maps back), taking the page from the element's
FlexForm or the new site setting vitec.storyDetailPid.
Spec raised to 1.17 with clause 7.15.2.1; the header had been left at 1.12
although entries up to 1.15 already existed, so today's two entries were
renumbered to 1.16 and 1.17.
Solr 10 dropped the ExtractingRequestHandler, so a dedicated Tika
container on the Solr VPS (Caddy route /tika/*, own basic-auth
credential; Tika itself has no auth) extracts file text during
indexing: TikaDownloadContentIndexer listens on
BeforeDocumentIsProcessedForIndexingEvent, resolves the file through
the existing DownloadFileResolver and appends the text (mime
whitelist, 30 MB cap, 100k chars, fail-soft) to the document's content
field. Extractions are cached in var/tika-cache keyed on
path+size+mtime - a full re-index of 177 downloads drops from 2:12 min
to 27 s, replacing a file re-extracts naturally. Datasheet
specifications ("625i", "genlock") are now searchable. Spec v1.15.
GET /search?type=7384&tx_solr[queryString]=<input> answers term
completions from the index (spell field) with document counts as lean
JSON - no page envelope, synonyms apply automatically. Two deliberate
deviations from the shipped example, which predates TYPO3 v14: the
plugin runs as USER_INT (config.no_cache is gone, and a cached USER
would pin the first query's suggestions for every later request), and
showTopResults is off (the top-result shape is hardcoded upstream with
the raw document type and full indexed content). Documented in spec
v1.12 clause 7.16.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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>
VITEC Import module: Products tab is now a searchable/sortable product
overview. "Edit Product" opens an XLSX upload with per-field source
mapping (component + cell), old/new preview and checkbox apply via
DataHandler; the mapping and manual matches are persisted and preselect
the next workbook. Category workbooks are detected and rejected.
- new: ProductXlsxReader (PhpSpreadsheet), ProductTextImportController,
Products/ProductTexts templates, 4 module routes
- related products: per-pair card text in new side table
tx_vitec_product_related_text (survives MM rewrites), emitted as
`cardtext` in the product JSON; missing MM relations added add-only
- card copy read from Body Copy (D) with fallback to CTA/Card Copy (E) -
the workbooks fill either depending on row type
- product detail page <title> now uses seotitle with title fallback
(provider made singleton and fed from the JSON renderer)
- per-user recent-search badges; last loaded workbook stored per product
(tx_vitec_product_workbook), Edit Product reopens on it
- composer: add phpoffice/phpspreadsheet ^5.9
- diagnostics: migrations/check_workbook.php
- vitec_usecaselist: layout + record selection like marketlist
- new plugin vitec_solutionlist (spec 7.13.3, key "solutions")
- tx_vitec_domain_model_usecase: detail_page -> resolved detailUrl
(also gives story cards in vitec_modelcard a link for the first time)
- "Show Toolbar" checkbox on product/market/solution/usecase lists
- spec bumped to v1.9
BREAKING: vitec_productlist and vitec_usecaselist now emit an object
instead of a bare array. Consumers must read products.products and
usecases.usecases. Also found: productlist had a configurable layout
that was never serialised; it is emitted now, but keeps its own 0-3
vocabulary instead of grid/list/carousel.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
New CLI command vitec:import-downloads: reads the JSON export of the
old site (www.vitec.com/import), cuts it out of the surrounding page
template by brace counting, and imports the downloads idempotently by
slug. Scope is deliberately narrow: only files under
/fileadmin/downloads/Collateral/, records without title or file are
skipped, records sharing one file_url are merged. Files are fetched
resumably into fileadmin/downloads/Collateral/ and stored on pid 29.
Legacy filenames are normalized on fetch so every imported file
matches the <prefix>__<filetype>__<NN>-<letter> version convention:
__NN_A -> __NN-A, ___NN -> __NN, __NNA -> __NN-A, and a bare __NN
gets -A appended as its initial revision. Verified against the full
export: all 179 names match afterwards, none of the already-correct
ones change.
tx_vitec_domain_model_download gains a second category field "type"
(display taxonomy: Datasheet, Success Story, Brochure, Software) next
to the filename-driven filetype categories. No SQL change needed -
the core generates columns for category fields. The three download
renderers emit the field as a string analogous to filetype; MM rows
are distinguished by fieldname, existing queries filter on it and
remain unaffected.
Import values are matched via the custom columns sys_category.filetype
and .type (falling back to title); missing categories are created
(filetype under --category-parent, default 4; type under a "Download
Type" parent).
getDownloadFile() in the three download renderers gains a filepath
fallback (FAL -> convention -> filepath) as a safety net for any
future filename that escapes the convention - previously such records
emitted file: null.
Architecture spec bumped to v1.7.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>