---
title: "Using Fluid in TYPO3"
manual: "TYPO3 Explained"
version: "main"
permalink: "https://docs.typo3.org/permalink/t3coreapi:fluid-usage-in-typo3@main"
source: "ApiOverview/Fluid/UsingFluidInTypo3.rst"
rendered: "2026-09-20T15:52:37+00:00"
---

# Using Fluid in TYPO3 {#fluid-usage-in-typo3}

Here are some examples of how Fluid can be used in TYPO3:

-   Create a template (theme) using a combination of TypoScript
    [FLUIDTEMPLATE](https://docs.typo3.org/m/typo3/reference-typoscript/main/en-us/ContentObjects/Fluidtemplate/Index.html#cobj-fluidtemplate) and Fluid.
    Check out the [TYPO3 site package tutorial](https://docs.typo3.org/m/typo3/tutorial-sitepackage/main/en-us/Index.html#start) which walks you through the
    creation of a sitepackage extension.
-   [Create a custom content element type (CType)](https://docs.typo3.org/permalink/t3coreapi:adding-your-own-content-elements@main) in addition to the already existing
    content elements TYPO3 supplies.
-   [Extbase-based controllers](https://docs.typo3.org/permalink/t3coreapi:extbase-controller-overview@main) have a default Fluid
    view in `$this->view`.
-   Use Fluid to create emails using the [TYPO3 Mail API](https://docs.typo3.org/permalink/t3coreapi:mail-fluid-email@main).
-   Use Fluid in [backend modules](https://docs.typo3.org/permalink/t3coreapi:backend-modules-template@main), either with or
    without Extbase.
-   Use the [generic view factory](https://docs.typo3.org/permalink/t3coreapi:generic-view-factory@main) to create a
    Fluid view.

-   [ViewHelper namespaces](https://docs.typo3.org/permalink/t3coreapi:viewhelper-namespaces@main)
-   [Using Fluid components](https://docs.typo3.org/permalink/t3coreapi:using-fluid-components@main)
-   [Using the generic view factory (ViewFactoryInterface)](https://docs.typo3.org/permalink/t3coreapi:using-the-generic-view-factory-viewfactoryinterface@main)

## ViewHelper namespaces {#fluid-syntax-viewhelpers-import-namespaces}

### Defining global Fluid namespaces {#defining-global-fluid-namespaces}

<!-- TODO: no Markdown rendering for "versionchanged" -->

The deprecated configuration of Fluid namespaces via
$GLOBALS['TYPO3_CONF_VARS']['SYS']['fluid']['namespaces'] has been
removed in favour of using the extension-level configuration file
Configuration/Fluid/Namespaces.php.

The extension-level configuration file [`Configuration/Fluid/Namespaces.php`](../../ExtensionArchitecture/FileStructure/Configuration/Fluid/Index.md#file-extension-configuration-fluid-namespaces-php)
registers and extends global Fluid namespaces.

For example, we can define two global namespaces with the identifiers
'myext' and 'mycmp':

**EXT:my_extension/Configuration/Fluid/Namespaces.php**

```php
<?php

return [
  'myext' => ['MyVendor\\MyExtension\\ViewHelpers'],
  'mycmp' => ['MyVendor\\MyExtension\\Components'],
];

```

Assuming you have defined a Fluid component in
`EXT:my_extension/Resources/Private/Components/Button/Button.fluid.html`
then you can access the Button component via

**EXT:my_extension/Resources/Private/Templates/SomeOtherTemplate.fluid.html**

```html
<mycmp:button title="{title}" teaser="{teaser}" />
```

It is possible to override ViewHelpers that are in another extension. This is
done by TYPO3 reading and merging [`Configuration/Fluid/Namespaces.php`](../../ExtensionArchitecture/FileStructure/Configuration/Fluid/Index.md#file-extension-configuration-fluid-namespaces-php)
files in loaded extensions in the usual loading order. Loading order can
be changed by declaring dependencies in `composer.json`. In other words,
if an extension registers a
namespace that has already been registered by another extension, Fluid will merge
the namespaces.

Example (my_extension2 depends on my_extension1):

**EXT:my_extension1/Configuration/Fluid/Namespaces.php**

```php
<?php

return [
  'myext' => ['MyVendor\\MyExtension1\\ViewHelpers'],
];

```

**EXT:my_extension2/Configuration/Fluid/Namespaces.php**

```php
<?php

return [
  'myext' => ['MyVendor\\MyExtension2\\ViewHelpers'],
];

```

This results in namespace definition:

**The resulting namespace definition**

```php
[
    'myext' => [
        'MyVendor\\MyExtension1\\ViewHelpers',
        'MyVendor\\MyExtension2\\ViewHelpers',
    ],
];
```

The processing order is in reverse, which means that
`<myext:demo />` would first check for
`EXT:my_extension2/Classes/ViewHelpers/DemoViewHelper.php`, and then
fall back to `EXT:my_extension1/Classes/ViewHelpers/DemoViewHelper.php`.

### Importing Fluid namespaces locally {#importing-fluid-namespaces-locally}

Say you have defined a Fluid component in
`EXT:my_extension/Resources/Private/Components/Button/Button.fluid.html`.
Instead of defining the Fluid namespace globally you can specify
the Fluid namespace like this:

**EXT:my_extension/Resources/Private/Templates/SomeOtherTemplate.fluid.html**

```html
<html
    xmlns:my="http://typo3.org/ns/MyVendor/MyExtension/Components"
    data-namespace-typo3-fluid="true"
>

<my:button title="{title}" teaser="{teaser}"/>
```

The namespace here is 'my'. For further information visit
[ViewHelper namespaces](https://docs.typo3.org/other/typo3fluid/fluid/main/en-us/Syntax/ViewHelpers.html#viewhelper-namespaces-syntax)
in Fluid explained.

## Using Fluid components {#using-fluid-components}

### Description {#description-fluid-components}

With version 4.3 the concept of components was introduced into Fluid.

### Introduction to Fluid components {#what-is-fluid-components}

The typical look of a component is like a normal Fluid template, except
that it defines all of its arguments with the
[Argument ViewHelper \<f:argument>](https://docs.typo3.org/other/typo3/view-helper-reference/main/en-us/Global/Argument.html#typo3fluid-fluid-argument).
The [Slot ViewHelper \<f:slot>](https://docs.typo3.org/other/typo3/view-helper-reference/main/en-us/Global/Slot.html#typo3fluid-fluid-slot)
can be used to receive other HTML content. With the Slot ViewHelper it is possible to nest components.

Here is an example of how you could define a Fluid component:

**EXT:my_extension/Resources/Private/Components/Molecule/TeaserCard/TeaserCard.fluid.html**

```html
<html
    xmlns:my="http://typo3.org/ns/MyVendor/MyExtension/Components"
    data-namespace-typo3-fluid="true"
>

<f:argument name="title" type="string" />
<f:argument name="link" type="string" />
<f:argument name="icon" type="string" optional="{true}" />

<a href="{link}" class="teaserCard">
    <f:if condition="{icon}">
        <my:atom.icon identifier="{icon}">
    </f:if>
    <div class="teaserCard__title">{title}</div>
    <div class="teaserCard__content"><f:slot /></div>
</a>
```

The example also demonstrates that components can (and should) use other components, in this
case `<my:atom.icon>`.
Depending on the use case, it might also make sense to pass the output of one component
to another component via a slot:

**EXT:my_extension/Resources/Private/Templates/SomeTemplate.fluid.html**

```html
<html
    xmlns:my="http://typo3.org/ns/MyVendor/MyExtension/Components"
    data-namespace-typo3-fluid="true"
>

<my:molecule.teaserCard
    title="TYPO3"
    link="https://typo3.org/"
    icon="typo3"
>
    <my:atom.text>{content}</my:atom.text>
</my:molecule.teaserCard>
```

You can learn more about components in
[Defining Components](https://docs.typo3.org/other/typo3fluid/fluid/main/en-us/Usage/Components.html#components-definition). Note
that this is part of the Fluid Standalone documentation, which means that it doesn't mention
TYPO3 specifics.

### Registering component collections {#register-fluid-components}

In order to use Fluid components, register a component collection
within the file [`Configuration/Fluid/ComponentCollections.php`](../../ExtensionArchitecture/FileStructure/Configuration/Fluid/Index.md#file-extension-configuration-fluid-componentcollections-php)

**EXT:my_extension/Configuration/Fluid/ComponentCollections.php**

```php
<?php

return [
  'MyVendor\\MyExtension\\Components' => [
    'templatePaths' => [
      10 => 'EXT:my_extension/Resources/Private/Components',
    ],
  ],
];

```

in which you define the path where your Fluid components can be found.
Components in these collections can then be used in any Fluid template.

**EXT:my_extension/Resources/Private/Templates/Template.fluid.html**

```html
<html
    xmlns:my="http://typo3.org/ns/MyVendor/MyExtension/Components"
    data-namespace-typo3-fluid="true"
>

<my:organism.header.navigation />
```

Note that, by default, component collections use a folder structure that
requires a separate directory for each component.
That means, for example, if you have defined a `<my:organism.header.navigation />`
Fluid component then the template file
should be stored in `EXT:my_extension/Resources/Private/Components/Organism/Header/Navigation/Navigation.fluid.html`.

All arguments that are passed to a component need to be defined with
`<f:argument>` in the component template, for example
`Navigation.fluid.html`.

It is possible to adjust these configurations per collection:

-   using `templateNamePattern` allows you to use a different folder structure,
    available variables are `{path}` and `{name}`. For example,
    with `<my:organism.header.navigation>`, `{path}` would be
    `Organism/Header` and `{name}` would be `Navigation`.
-   setting `additionalArgumentsAllowed` to `true` allows passing undefined arguments
    to components.

Here is an example where these configurations are used.

**EXT:my_extension/Configuration/Fluid/ComponentCollections.php**

```php
<?php

return [
  'MyVendor\\MyExtension\\Components' => [
    'templatePaths' => [
      10 => 'EXT:my_extension/Resources/Private/Components',
    ],
    'templateNamePattern' => '{path}/{name}',
    'additionalArgumentsAllowed' => true,
  ],
];

```

Using this example, `<my:organism.header.navigation />` would point to
`EXT:my_extension/Resources/Private/Components/Organism/Header/Navigation.fluid.html`
(note the missing `Navigation` folder).

It is possible to influence certain aspects of Fluid components using PSR-14 events,
see [PSR-14 events for Fluid components](https://docs.typo3.org/c/typo3/cms-core/main/en-us/Changelog/14.1/Feature-108508-PSR-14EventsForFluidComponents.html#feature-108508-1765987847).

### History of Fluid components {#history-fluid-components}

In TYPO3 v13 it became possible to use components in TYPO3 projects by creating a custom
`ComponentCollection` class that essentially connects a folder of template files
to a Fluid ViewHelper namespace. Using that class it is also possible to use an
alternative folder structure for a component collection and to allow
arbitrary arguments to be passed to components in that collection.

### Migration and co-existence with class-based collections {#migration-co-existence-fluid-components}

Since TYPO3 v14 you should use the configuration-based component collections over
the class-based. A configuration-based component collection is a collection defined
by the configuration file `ComponentCollections.php`. In contrast to that, a
class-based component required custom PHP code in TYPO3 v13, see
[Fluid components in Fluid explained](https://docs.typo3.org/other/typo3fluid/fluid/main/en-us/Usage/Components.html#components-setup).
Most use cases can easily be migrated to the configuration-based approach, since
they usually just consist of boilerplate code around the configuration options.

In fact, you can use both component collection types side by side. For more
advanced use cases, it might still be best to ship a custom class to define
a component collection. Since the configuration-based approach is not available in TYPO3 v13,
it is possible to ship both variants to provide backwards-compatibility:
if a specific component collection is
defined both by class and by configuration, in TYPO3 v13 the class will be used,
while in TYPO3 v14 the configuration will be used and the class will be ignored completely.

### Extending component collections from other extensions {#extending-component-collections-fluid-components}

It is possible to extend the configuration of other extensions using the
introduced configuration file. This allows integrators to merge their own set of
components into an existing component collection:

**EXT:vendor_extension/Configuration/Fluid/ComponentCollections.php**

```php
<?php

return [
  'SomeVendor\\VendorExtension\\Components' => [
    'templatePaths' => [
      10 => 'EXT:vendor_extension/Resources/Private/Components',
    ],
  ],
];

```

**EXT:my_extension/Configuration/Fluid/ComponentCollections.php**

```php
<?php

return [
  'SomeVendor\\VendorExtension\\Components' => [
    'templatePaths' => [
      1765990741 => 'EXT:my_extension/Resources/Private/Extensions/VendorExtension/Components',
    ],
  ],
];

```

For template paths, the familiar rule applies: they will be sorted by their
keys and will be processed in reverse order. In this example, if `my_extension`
defines a component that already exists in `vendor_extension`, it will override
the original component in `vendor_extension`.

### PSR-14 events related to Fluid components {#psr-14-events-fluid-components}

Three PSR-14 events are available to influence the processing and rendering
of Fluid components that are registered using the new configuration file
(see [Feature: #108508 - Fluid components integration](https://docs.typo3.org/c/typo3/cms-core/main/en-us/Changelog/14.1/Feature-108508-FluidComponentsIntegration.html#feature-108508-1765987901)).

-   [ModifyComponentDefinitionEvent](https://docs.typo3.org/permalink/t3coreapi:modifycomponentdefinitionevent@main)
-   [ProvideStaticVariablesToComponentEvent](https://docs.typo3.org/permalink/t3coreapi:providestaticvariablestocomponentevent@main)
-   [RenderComponentEvent](https://docs.typo3.org/permalink/t3coreapi:rendercomponentevent@main)

## Using the generic view factory (`ViewFactoryInterface`) {#generic-view-factory}

You can [inject](https://docs.typo3.org/permalink/t3coreapi:dependency-injection@main) an instance of the
`\TYPO3\CMS\Core\View\ViewFactoryInterface` to create an instance of a
`\TYPO3\CMS\Core\View\ViewInterface` where you need one.

> [!NOTE]
> [Extbase-based controllers](https://docs.typo3.org/permalink/t3coreapi:extbase-controller-overview@main) create a view
> instance based on this factory by default and which is accessible as
> `$this->view`.

**EXT:my_extension/Classes/Controller/MyController.php (Not Extbase)**

```php
<?php

namespace MyVendor\MyExtension\Controller;

use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Core\View\ViewFactoryData;
use TYPO3\CMS\Core\View\ViewFactoryInterface;

final readonly class MyController
{
  public function __construct(
    private ViewFactoryInterface $viewFactory,
  ) {}

  public function myAction(ServerRequestInterface $request): string
  {
    $viewFactoryData = new ViewFactoryData(
      templateRootPaths: ['EXT:my_extension/Resources/Private/Templates'],
      partialRootPaths: ['EXT:my_extension/Resources/Private/Partials'],
      layoutRootPaths: ['EXT:my_extension/Resources/Private/Layouts'],
      request: $request,
    );
    $view = $this->viewFactory->create($viewFactoryData);
    $view->assign('mykey', 'myValue');
    return $view->render('path/to/template');
  }
}

```

The `ViewFactoryInterface` needs an instance of
`\TYPO3\CMS\Core\View\ViewFactoryData`, which is a data object and should
therefore be created via `new`.

Best practices in creating a `ViewFactoryData`
instance:

-   Hand over request of type `\Psr\Http\Message\ServerRequestInterface`
    if possible. See [Getting the PSR-7 request object](https://docs.typo3.org/permalink/t3coreapi:getting-typo3-request-object@main).
-   Use the tuple `$templateRootPaths`, `$partialRootPaths` and
    `$layoutRootPaths` if possible by providing an array of "base" paths
    like `'EXT:my_extension/Resources/Private/(Templates|Partials|Layouts)'`
-   Avoid using parameter `$templatePathAndFilename`
-   Call `render('path/within/templateRootPath')` without file-ending on the
    returned ViewInterface instance.
