New JsonCacheHeaders middleware (outer, frontend stack): GET/HEAD 200 responses under /_json get a single Cache-Control: no-cache, Expires: 0 and a content md5 ETag; If-None-Match answers as empty 304. Logged-in visitors (fe_typo_user) keep TYPO3 headers. Expires: 0 is deliberate so mod_expires leaves the response alone. .htaccess: the global Header unset ETag now skips /_json (KEEP_ETAG env, carried across the mod_rewrite internal redirect as REDIRECT_KEEP_ETAG). Fulfils tickets 0011-FE point 3 and 0055-BE question 6; asset immutable headers were already live.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Site set Vitecset: new bool setting vitec.ssr.enabled (default off,
backend switch under Site Management > Settings > VITEC Settings)
- SsrFlagService derives var/vitec-ssr-on.flag from the setting;
SyncSsrFlag middleware (frontend + backend) re-syncs per request
because TYPO3 v14 fires no event on site settings save;
vitec:ssr-flag CLI command for status/--sync
- public/.htaccess: flag-gated block proxies page requests [P] to
https://vitec-ssr.evomedien.de (mod_proxy incl. https target verified
on this host 2026-11-09), same exclusions as the SPA fallback block;
completely inert while the flag file is absent
- Emergency off without TYPO3: delete var/vitec-ssr-on.flag
- Tested end to end: flag on -> pages proxied to VPS Caddy (502 while
the SSR node is not deployed yet), /_json untouched; flag off ->
SPA shell exactly as before
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
per sub-market (25, grouped by the 9 main markets): VITEC-styled Read me,
a Page-layout sheet embedding the Figma design with section markers,
DB-live dropdowns, soft character limits, a hidden Meta sheet and named
input cells. Names must NOT start with a cell-reference token - Excel
silently strips s1_-style names as repairs.
vitec:import-submarket-workbooks (dry-run default, idempotent) finds or
creates the page below its main market (hidden, layout 21), fills the six
colPos slots updating in place and never deleting, links detail_page on
the market record, downloads asset URLs into fileadmin/submarket_import/
for editorial review and writes the flexforms as DataHandler arrays.
Reading is three-layered after a bruising day of real-world Excel: named
ranges first, then a label scan over the locked column A with section
tracking - a customer save stripped ALL defined names and shifted rows,
so fixed addresses are not a contract.
Learned and fixed along the way: DuplicationBehavior moved to
Resource\Enum in v14; sys_file_reference rows via DataHandler need
pid/tablenames/uid_foreign or are dropped silently; handing DataHandler a
fresh NEW reference per run STACKS live references on re-import (caught
by a double-run test), so attachments are now content-idempotent - the
existing live reference is reused or retargeted and surplus duplicates
are deleted via cmdmap; RequestFactory replaces GeneralUtility::getUrl so
download failures carry their reason - which surfaced that the dev basic
auth blocked the server itself (server IP + loopback now allowlisted,
which a future SSR needs anyway) and that the core resource-consistency
check rightly rejects HTML masquerading as PNG.
Verified end to end on Broadcast & Media from a clean slate, twice in a
row: 12 elements in colPos 110-160, layout-21 payload, both images
attached exactly once with publicUrl in the JSON; second run reports
nothing but unchanged.
feedback widget served from /api/fe-comment/widget.js, note pad in
localStorage, submissions mailed via /api/fe-comment/submit with
recipients from the extension configuration; classic sites get the
script injected via AssetCollector when the jsonOutput setting is off.
An enabled master switch serves the widget EMPTY when off (no 404, no
console errors) and rejects submissions - the go-live kill switch, no
front-end build change needed
- URL swap finished: /_json prefix middleware, SPA fallback live with a
dedicated root rule (REQUEST_FILENAME of / is a directory) and a
query-string exception for the TYPO3 v14 install tool entry
(?__typo3_install on the site root - the backend Settings/Environment
modules depend on it); /api/ as a whole stays with TYPO3
- MailMessage::send() no longer exists in v14: fe_comment and the form
EmailDelivery (latently broken since the core upgrade) now send through
the Mailer service. Mail transport moved to SMTP against the local exim
so delivery errors surface instead of bouncing into the blackhole -
exim verifies the envelope sender, which therefore must be a routable
existing address (transport config lives in the untracked settings.php)
- Related-product card texts editable on the product record (table rebuilt
with uid/pid, TCA + inline field, one-time migration script); shared
RteCompare for the module badge and the CLI comparison - batch dry-run
now reports 0 writes instead of flagging every richtext field
- Workbook clarification cases executed: VisionIO-SD14, VisionSC-SD14 and
both Diamond OG records imported (40 fields, live-verified); ArtioSign
and ArtioView created hidden (uid 109/110) via
create_artio_records.php - the product table has no sorting column;
WallControl_10 mapping REVERTED and parked: the dry run revealed
aetria-wallcontrol already carries its own agency workbook, which
WallControl_10 would have overwritten. Manifest now 75 product /
24 family / 1 open