Configuration

Feature Flags

To modify the settings for this extension, you can use either LocalConfiguration.php or AdditionalConfiguration.php.

headless.storageProxy

Enables the ability to set a storage proxy in the site configuration (and its variants) & serve files via proxy from the same domain.

Feature flag requires TYPO3 >= 10.4.10.

WARNING If you install TYPO3 >= 10.4.18, please update ext:headless to version >= 2.5.3.

$GLOBALS['TYPO3_CONF_VARS']['SYS']['features']['headless.storageProxy'] = true;
Copied!

headless.redirectMiddlewares

Enables new and replaces core middlewares for handling redirects. Headless mode requires redirects to be handled by the frontend app.

$GLOBALS['TYPO3_CONF_VARS']['SYS']['features']['headless.redirectMiddlewares'] = true;
Copied!

To enable headless support for EXT:redirect, add the following flag to your site configuration's YAML file:

headless: true
Copied!

headless.nextMajor

Enables new APIs/behaviors of ext:headless, which may contain breaking changes and require an upgrade path for your application. Use with caution.

$GLOBALS['TYPO3_CONF_VARS']['SYS']['features']['headless.nextMajor'] = true;
Copied!

headless.elementBodyResponse

Available since 2.6.

Enables clean output middleware for plugins. Clean output is available for POST/PUT/DELETE method requests. To get clean output for plugins on a page, enable this flag and add headless to the site configuration, then send the responseElementId field with the ID of the plugin in the body with plugin data.

LocalConfiguration.php

$GLOBALS['TYPO3_CONF_VARS']['SYS']['features']['headless.elementBodyResponse'] = true;
Copied!

Site configuration:

Add the following flag to your site configuration's YAML file:

headless: true
Copied!

Example POST request with plugin form. Replace #ELEMENT_ID# with the ID of the plugin from the page response.

POST https://example.tld/path-to-form-plugin
Content-Type: application/x-www-form-urlencoded

responseElementId=#ELEMENT_ID#&tx_form_formframework[email]=email&tx_form_formframework[name]=test...
Copied!

To find a nested element, use the new flag responseElementRecursive, where responseElementId is the child (nested element). Example request:

POST https://example.tld/path-to-form-plugin
Content-Type: application/x-www-form-urlencoded

responseElementId=#ELEMENT_ID#&responseElementRecursive=1&tx_form_formframework[email]=email&tx_form_formframework[name]=test...
Copied!

headless.simplifiedLinkTarget

Available since 2.6.

Enables simplified target links' property.

$GLOBALS['TYPO3_CONF_VARS']['SYS']['features']['headless.simplifiedLinkTarget'] = true;
Copied!

Simplified output returns only the value, e.g., _blank for the target attribute instead of the HTML string target="_blank".

headless.jsonViewModule

Available since 3.0.

Enables the experimental JsonView backend module, which allows previewing the page JSON response in the backend module when passing specific pageType, pageArguments, usergroups, language.

This flag requires an additional extension friendsoftypo3/headless-dev-tools.

$GLOBALS['TYPO3_CONF_VARS']['SYS']['features']['headless.jsonViewModule'] = true;
Copied!

headless.workspaces

Enables EXT:workspaces preview support.

$GLOBALS['TYPO3_CONF_VARS']['SYS']['features']['headless.workspaces'] = true;
Copied!

To enable headless support for EXT:workspaces, add the following flag to your site configuration's YAML file:

headless: true
Copied!

headless.pageTitleProviders

Enables support for the PageTitle API.

$GLOBALS['TYPO3_CONF_VARS']['SYS']['features']['headless.pageTitleProviders'] = true;
Copied!

Availability of Feature Toggles by Version

Flag

2.x

3.x

4.x

FrontendBaseUrlInPagePreview

available

removed

removed

headless.frontendUrls

>= 2.5

available

removed

headless.storageProxy

>= 2.4

available

available

headless.redirectMiddlewares

>= 2.5

available

available

headless.nextMajor

>= 2.2

currently not used

currently not used

headless.elementBodyResponse

>= 2.6

available

available

headless.simplifiedLinkTarget

>= 2.6

removed

not available

headless.jsonViewModule

not available

>= 3.0

>= 3.0

headless.workspaces

not available

>= 3.1

>= 3.1

headless.pageTitleProviders

not available

not available

>= 4.2.3

EXT:form

If EXT:form is enabled in the TYPO3 instance, EXT:headless provides support for handling forms in headless mode.

Standard forms designed in the form editor in TYPO3 backend should work out of the box, but the headless extension supports additional small tweaks/features to help frontend developers better handle forms on their end.

All options are added in YAML files with standard form configuration in TYPO3.

i18n

In many cases in headless mode, frontend developers need some translated strings for common elements like buttons, help messages, etc.

With EXT:headless, you can add additional configuration in the root line of the form config:

i18n:
  identifier: 'i18n'
  properties:
     someButtonLabel: 'Submit or Cancel'
     someHelpMessage: 'You need to fill out this form'
     requiredFields: 'These fields are required'
Copied!

The above block will be automatically translated by provided XLF files like a standard form in fluid.

This block will be translated & available in the "i18n" part of the response. More about form output can be found in the Form Decorator section.

Form Decorator

The headless extension provides an out-of-the-box simple decorator for form definition output. The decorator simplifies the response and provides an API to customize your response for your specific needs.

In the rendering options of the form, you can define your custom project/form decorator. If the option is not defined, the headless extension defaults to:

FriendsOfTYPO3\Headless\Form\Decorator\FormDefinitionDecorator

You can override this at any time by specifying it in the form's config YAML:

renderingOptions:
  formDecorator: Your-Vendor\YourExtension\Form\CustomDefinitionDecorator
Copied!

More about form output decorators can be found in customize form output.

Validators

To help frontend developers create validation handling in a frontend context, you can add small tweaks to form element definitions to ease development for your frontend team.

In the form element definition, you can add an option to errorMessage for your defined validators with the error code value. This code will be picked up and translated by standard TYPO3 XLF form files.

For example:

renderables:
   -
      type: 'Page'
      identifier: 'page-1'
      label: 'Step'
      renderables:
         -
            properties:
               options:
                  Mr: 'Mr'
                  Mrs: 'Mrs'
               elementDescription: ''
               fluidAdditionalAttributes:
                  required: required
            type: 'RadioButton'
            identifier: 'salutation'
            label: 'Salutation'
            validators:
               -
                 identifier: 'NotEmpty'
                 errorMessage: 1221560910
Copied!

When creating a RegexValidator, there are some differences when handling regular expressions by PHP & JS. To help frontend developers create consistent frontend/backend validation, we introduced a small option for regex validators in TYPO3.

For example:

renderables:
   -
      type: 'Page'
      renderables:
         -
           type: 'Text'
           identifier: 'testField'
           label: 'Test field'
           validators:
             -
                identifier: 'RegularExpression'
                options:
                  regularExpression: '/^[a-z]+$/'
                FERegularExpression:
                  expression: '^[a-z]+$'
                  flags: 'i'
                errorMessage: 1221565130
Copied!

If the headless form decorator finds the option FERegularExpression in the validator definition, it will override options.regularExpression with the value of the FERegularExpression option before sending the output to the frontend developer.

Custom Options

When you need a select/radio/checkbox with custom options fetched from, for example, a database or another external source, you need to create a Custom FormModel. In headless mode, we do not render HTML and render all the options, so we introduced a small interface:

FriendsOfTYPO3\Headless\Form\CustomOptionsInterface

and customOptions in the definition of the form element:

- defaultValue: ''
  type: 'SingleSelectWithCountryList'
  identifier: 'country'
  label: 'Country'
  properties:
     customOptions: 'YourVendor\Your-Ext\Domain\Model\YourCustomOptionClassImplementingInterface'
Copied!

When the above option is set with a class that implements the correct interface, the options of the select element will be replaced by the values returned by the specified class.

To make rendering of the element easier for frontend developers, we introduced the option to override the type returned to the frontend developer. For example, when you set FEOverrideType in the renderingOptions of a custom element:

type: 'SingleSelectWithCountryList'
renderingOptions:
  FEOverrideType: 'Select'
Copied!

We use this value to override the type, so the response to the frontend developer will be:

{
  "type": "Select"
}
Copied!

instead of:

{
  "type": "SingleSelectWithCountryList"
}
Copied!

JSON Redirect

EXT:headless supports handling finishers. For example, after handling correctly sent form data, you can use TYPO3 core's RedirectFinisher to redirect to a thank you page. To have more control on the frontend side, we provide in the headless extension:

JsonRedirectFinisher

This is based on the core RedirectFinisher but, instead of delay & statusCode options, has an option for a message that can be handled by the frontend developer to display a message for the user before redirecting to the defined page.

Also, JsonRedirect does not redirect by itself but generates a message (default is null) and URI for redirection by the frontend developer.

To use JsonRedirect, define it in the setup.yaml of your extension form's setup:

TYPO3:
  CMS:
    Form:
      prototypes:
        standard:
          finishersDefinition:
            JsonRedirect:
              implementationClassName: 'FriendsOfTYPO3\Headless\Form\Finisher\JsonRedirectFinisher'
Copied!

[BETA] JsonView Backend Module

JsonView Module icon with label

The JsonView module is an experimental approach for previewing JSON responses of a page in different contexts like pageType, page arguments, usergroup, language, and show/hide hidden content.

!WARNING This is an experimental module, please don't use it on a production environment at this time.

Root page for the API endpoint Root page for the API endpoint

PageTypeModes

You can set the context in which you want to preview a page.

By default, there are 3 settings available:

  • default - standard response with page data and content
  • initialData - standard response from pageType=834
  • detailNews (commented out) - example of calling the detail action of the news extension for test purposes
pageTypeModes:
  default:
    title: Default page view
    pageType: 0
    bootContent: 1
    parserClassname: FriendsOfTYPO3\Headless\Service\Parser\PageJsonParser

  initialData:
    title: Initial Data
    pageType: 834
    parserClassname: FriendsOfTYPO3\Headless\Service\Parser\DefaultJsonParser

#  Example of detail news preset
#
#  detailNews:
#    title: Detail news
#    pageType: 0
#    bootContent: 1
#    arguments:
#      tx_news_pi1:
#        action: detail
#        controller: News
#        news: 1
Copied!

Custom YAML Configuration

You can always create your own YAML configuration and set it in the extension configuration.

Root page for the API endpoint

Content element categories

Headless default configuration for content element categories in TypoScript lib.contentElement is to look in root (page uid=0). However depending on your project needs this may not ideal.

(as of TYPO3 v12 you cannot use together pidInList = root and recursive = 99)

Alternative approach for categories may be to use categories from current rootPage which mitigates this problem.

To begin you need to unset previous pidInList value

lib.contentElement.fields.categories.10.select.pidInList >
Copied!

If you need categories from current rootPage

lib.contentElement.fields.categories.10.select.pidInList >
lib.contentElement.fields.categories.10.select.pidInList.data = leveluid : 0
Copied!

You can add 'recursive' if categories may be stored under current rootPage

lib.contentElement.fields.categories.10.select.pidInList >
lib.contentElement.fields.categories.10.select.pidInList.data = leveluid : 0
lib.contentElement.fields.categories.10.select.recursive = 99
Copied!