--- name: typo3-menu-dataprocessor description: Create navigation menus in TYPO3 v13+ using the `menu` and `language-menu` data processors with PAGEVIEW/FLUIDTEMPLATE. Use this skill when building or modifying any kind of page navigation — main menus, breadcrumbs, language switchers, directory listings, sitemaps, or category-based menus — inside a TYPO3 site package. Covers TypoScript data processor configuration, all `special` menu types, available options, Fluid template rendering of menu items, and nested/multi-level menus. license: CC-BY-4.0 compatibility: Requires a TYPO3 v13+ site package using PAGEVIEW or FLUIDTEMPLATE and an available frontend page tree/site-language configuration. --- # TYPO3 Menu via Data Processors ## Architecture Menus in modern TYPO3 (v13+) are created through **data processors** configured in TypoScript, then rendered in **Fluid templates**. The data processor produces an array of menu items available as a Fluid variable. Two data processors handle menus: | Alias | FQCN | Purpose | |-----------------|--------------------------------------------------------|------------------------------| | `menu` | `\TYPO3\CMS\Frontend\DataProcessing\MenuProcessor` | Page tree menus, breadcrumbs | | `language-menu` | `\TYPO3\CMS\Frontend\DataProcessing\LanguageMenuProcessor` | Language switcher | > [!NOTE] > The legacy `HMENU` cObject still works but data processors are the recommended approach for Fluid-based templates. --- ## 1. The `menu` Data Processor ### Minimal Setup (inside PAGEVIEW or FLUIDTEMPLATE) ```typoscript dataProcessing { 10 = menu 10.as = mainMenu } ``` This creates a single-level menu of direct child pages of the site root, accessible in Fluid as `{mainMenu}`. ### All Options | Option | Type | Description | |---------------------|---------|-----------------------------------------------------------------------------| | `as` | string | Variable name in Fluid template | | `levels` | int | Max depth of submenus to include (default `1`) | | `expandAll` | bool | `1` = include all submenus; `0` = only active branch | | `entryLevel` | int | Root level to start from (`0` = site root, negative counts from current) | | `excludeUidList` | string | Comma-separated page UIDs to exclude; supports `current` | | `excludeDoktypes` | string | Comma-separated doktypes to exclude (default: `6,254`) | | `includeNotInMenu` | bool | Include pages with "Page enabled in menus" unchecked | | `includeSpacer` | bool | Include spacer-type pages | | `titleField` | string | Field(s) for title with fallback, e.g. `nav_title // title` | | `special` | string | Activates a special menu type (see below) | | `special.value` | string | Value for the special type (page UIDs, etc.) | | `alwaysActivePIDlist`| string | Page UIDs always marked as active | | `protectLvar` | bool | Falls back to default language if no translation exists | | `dataProcessing` | array | Nested data processors applied per menu item | ### Special Menu Types Set `special` to one of: | Value | Purpose | Key extra options | |--------------|------------------------------------------|--------------------------------------| | `rootline` | Breadcrumb / rootline path | `special.range`, `special.reverseOrder` | | `directory` | Children of specific page(s) | `special.value` = parent page UIDs | | `list` | Explicit list of pages | `special.value` = page UIDs | | `categories` | Pages assigned to certain categories | `special.value` = category UIDs | | `browse` | Previous / next navigation | various sub-properties | | `keywords` | Pages sharing keywords with current page | `special.value`, `special.keywordsField` | | `updated` | Recently updated pages | `special.value`, `special.depth` | --- ## 2. The `language-menu` Data Processor ```typoscript dataProcessing { 20 = language-menu 20 { languages = auto as = languageMenu } } ``` ### Options | Option | Type | Description | |-------------------------|--------|-------------------------------------------------------| | `languages` | string | Comma-separated language IDs or `auto` (from site config) | | `as` | string | Variable name in Fluid | | `addQueryString.exclude`| string | Parameters to strip from language URLs | | `if` | if | Condition to enable/disable the processor | > For a full language menu implementation with browser-language auto-detection and cookie-based language persistence, use the **`typo3-language-menu`** skill. --- ## 3. Complete TypoScript Examples ### Main Menu (two levels, all expanded) ```typoscript lib.fluidPage = PAGEVIEW lib.fluidPage { paths { 10 = EXT:my_sitepackage/Resources/Private/Templates/ 20 = EXT:my_sitepackage/Resources/Private/ } dataProcessing { 10 = menu 10 { as = mainMenu levels = 2 expandAll = 1 } } } ``` ### Breadcrumb ```typoscript dataProcessing { 20 = menu 20 { special = rootline as = breadcrumb # Use record-transformation for structured data dataProcessing.10 = record-transformation } } ``` ### Language Switcher ```typoscript dataProcessing { 30 = language-menu 30 { languages = auto as = languageMenu } } ``` ### Directory Menu (children of a specific page) ```typoscript dataProcessing { 40 = menu 40 { special = directory special.value = 42 as = categoryMenu levels = 1 } } ``` ### Explicit Page List ```typoscript dataProcessing { 50 = menu 50 { special = list special.value = 10,20,30 as = footerMenu } } ``` ### Combined Real-World Setup ```typoscript lib.fluidPage = PAGEVIEW lib.fluidPage { paths { 10 = EXT:my_site_package/Resources/Private/Templates/ 20 = EXT:my_site_package/Resources/Private/ } dataProcessing { # Main navigation (2 levels, fully expanded) 10 = menu 10 { as = mainMenu levels = 2 expandAll = 1 } # Breadcrumb 20 = menu 20 { special = rootline as = breadcrumb dataProcessing.10 = record-transformation } # Language switcher 30 = language-menu 30 { languages = auto as = languageMenu } # Site data 40 = site 40.as = site } } ``` --- ## 4. Fluid Template Rendering ### Menu Item Properties Each item in the menu array exposes: | Property | Type | Description | |----------------|--------|----------------------------------| | `title` | string | Page title (respects `titleField`)| | `link` | string | URL to the page | | `target` | string | Link target attribute | | `active` | bool | Currently in rootline | | `current` | bool | Is the current page | | `spacer` | bool | Is a spacer page | | `hasSubpages` | bool | Has child items | | `children` | array | Sub-menu items (if multi-level) | | `data` | array | Full page record (`data.uid`, etc.) | ### Single-Level Menu ```html ``` ### Two-Level Dropdown Menu ```html ``` ### Breadcrumb ```html ``` ### Language Menu ```html ``` --- ## 5. Key Patterns ### Unique processor keys Use Unix timestamps or otherwise unique integers as processor keys to avoid collisions when multiple sets or extensions add processors: ```typoscript dataProcessing { 1763411533130 = menu 1763411533130.as = mainMenu } ``` ### Nested data processing Apply additional processors per menu item (e.g., `files` to attach media): ```typoscript dataProcessing.10 = menu dataProcessing.10 { levels = 2 as = mainMenu dataProcessing { 10 = files 10.references.fieldName = media } } ``` ### Breadcrumb with record-transformation Chain `record-transformation` inside the breadcrumb processor for structured data: ```typoscript dataProcessing.20 = menu dataProcessing.20 { special = rootline as = breadcrumb dataProcessing.10 = record-transformation } ``` ### Excluding pages ```typoscript dataProcessing.10 = menu dataProcessing.10 { as = mainMenu excludeUidList = 42,99,current } ``` --- ## 6. Best Practices & Common Pitfalls ### Breadcrumbs and Hidden Pages (`nav_hide`) When building breadcrumbs with `special = rootline`, the `MenuProcessor` will natively ignore any pages marked as "Hide in menu" (`nav_hide = 1`). Detail pages or structural folders are frequently hidden from the main navigation, causing broken or incomplete rootlines. **Agent Instruction:** When you are asked to implement or fix a breadcrumb menu, **always ask the user explicitly** if hidden pages should be included in the breadcrumb path. If the user says yes, you must add `includeNotInMenu = 1` to the TypoScript configuration. ### Never Build Navigation in Extbase Do not attempt to construct breadcrumbs or menus inside Extbase Controllers (e.g., by looping through `$GLOBALS['TSFE']->rootLine`). This is a fragile legacy approach that breaks TYPO3 caching mechanisms. * **Always** use a TypoScript `MenuProcessor` (e.g., `lib.breadcrumb`). * Call it from the Fluid template using the `f:cObject` viewhelper (e.g., ``) to seamlessly bridge dynamic plugin data into the global TypoScript object. --- ## Load References As Needed - Complete options reference: [references/menu-processor-options.md](references/menu-processor-options.md) - Fluid template patterns: [references/fluid-templates.md](references/fluid-templates.md) ## References - [Menu Guide](https://docs.typo3.org/m/typo3/reference-typoscript/main/en-us/Guide/Menu/Index.html) - [MenuProcessor Reference](https://docs.typo3.org/m/typo3/reference-typoscript/main/en-us/DataProcessing/MenuProcessor/Index.html) - [LanguageMenuProcessor Reference](https://docs.typo3.org/m/typo3/reference-typoscript/main/en-us/DataProcessing/LanguageMenuProcessor.html) - [Rootline / Breadcrumb](https://docs.typo3.org/m/typo3/reference-typoscript/main/en-us/DataProcessing/MenuProcessor/Rootline.html) - [Site Package Tutorial – Main Menu](https://docs.typo3.org/m/typo3/tutorial-sitepackage/main/en-us/Menu/Index.html) ## Completion And Boundaries Do not use this skill to replace a bespoke application navigation model; use it for TYPO3 page-tree menus and processors. Confirm whether hidden pages belong in breadcrumbs before changing `includeNotInMenu`. Complete only after active/current states, empty and multi-level branches, hidden-page behavior, translated links, and keyboard navigation have been verified for the requested menu.