Neos CMS bietet mit Fusion die Möglichkeit, dynamische Seiten vollständig ohne Fluid zu rendern.

In diesem Beispiel zeigen wir, wie man:

  • eigene URLs über Routes.yaml definiert
  • einen Controller aufruft
  • eine Node abhängig von der Sprache lädt
  • eine komplette Seite mit Fusion rendert
  • Events dynamisch ausgibt
  • hreflang-Links über Fusion erzeugt

Dabei bleibt der Controller sehr klein. Das eigentliche Rendering übernimmt Fusion.

 

1. Eigene URLs mit Routes.yaml

Zuerst definieren wir eigene URLs wie:

/en/2025/my-event /de/2025/mein-event /2025/mein-event

Die Routes.yaml kann zum Beispiel so aussehen:

- name: 'Event Detail with Language'

uriPattern: '{language}/{year}/{slug}'

defaults:

'@package': 'Vendor.Site'

'@controller': 'Event'

'@action': 'show' appendExceedingArguments: true

 

- name: 'Event Detail default Language'

uriPattern: '{year}/{slug}'

defaults:

'@package': 'Vendor.Site'

'@controller': 'Event'

'@action': 'show' language: 'de' appendExceedingArguments: true

Damit bekommen wir die Parameter language, year und slug, die an den Controller weitergegeben werden.

 

2. Der Controller

Der Controller lädt nur die passende Node und übergibt sie an Fusion.

final class EventController extends ActionController

{

protected $defaultViewObjectName = FusionView::class; #[Flow\Inject] protected ContextFactoryInterface $contextFactory; public function showAction(string $language, string $slug): void {

$context = $this->contextFactory->create([

'workspaceName' => 'live',

'dimensions' => ['language' => [$language]],

]);

$eventNode = $context->getNode(

'/sites/mysite/events/' . $slug

);

$this->view->assign('eventNode', $eventNode);

$this->view->assign('language', $language);

$this->view->assign('slug', $slug);

}

}

Der Controller enthält kein HTML und kein Layout. Er liefert nur die Daten.

 

3. Das Layout mit Fusion

Fusion übernimmt das komplette Rendering der Seite.

 

prototype(Vendor.Site:Layout.ControllerPage) < prototype(Neos.Fusion:Component) {

node = null

innerContent = ''

renderer = Neos.Fusion:Join {

doctype = '<!DOCTYPE html>'

html = afx`

<html lang="de">

<head>

<meta charset="utf-8" />

<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>{q(props.node).property('title')}</title>

<link

rel="stylesheet"

href="/_Resources/Static/Packages/Vendor.Site/Css/style.css"

/>

</head>

<body>

{props.innerContent}

</body>

</html>

`

}

}

Damit entsteht eine vollständige HTML-Seite direkt über Fusion.

 

4. Event-Inhalte ausgeben

Für das Event erstellen wir eine eigene Fusion-Komponente:

prototype(Vendor.Site:Document.EventPage) < prototype(Neos.Fusion:Component) {

node = ${node}

renderer = afx`

<article class="event-detail">

<h1>{q(node).property('title')}</h1>

<p class="event-date">

{q(node).property('eventDate')}

</p>

<div class="event-description">

{q(node).property('description')}

</div>

</article>

`

}

Anschließend wird die Event-Seite in das Layout eingesetzt:

Vendor.Site.EventController.show = Vendor.Site:EventController.Show prototype(Vendor.Site:EventController.Show) < prototype(Neos.Fusion:Component) {

@context {

node = ${eventNode}

}

renderer = Vendor.Site:Layout.ControllerPage {

node = ${node}

innerContent = Vendor.Site:Document.EventPage {

node = ${node}

}

}

}

Damit ist der Ablauf einfach: Controller lädt die Node, Fusion rendert das Layout und Fusion gibt den Event-Inhalt aus.

 

5. Mehrsprachige hreflang-Links

Auch hreflang-Links können direkt in Fusion erzeugt werden.

prototype(Vendor.Site:AlternateLanguages) < prototype(Neos.Fusion:Component) {

node = ${node}

supportedLanguages = ['de', 'en']

renderer = Neos.Fusion:Loop {

items = ${props.supportedLanguages}

itemName = 'lang'

itemRenderer = afx`

<link rel="alternate" hreflang={lang} href={EventHelper.getEventUrl(props.node, lang)}

/>

<link rel="alternate" hreflang="x-default" href={EventHelper.getEventUrl(props.node, 'de')} @if={lang == 'de'}

/>

`

}

}

Im Layout wird die Komponente so eingebunden:

<Vendor.Site:AlternateLanguages node={node} />

 

Fazit

Mit Routes.yaml, einem kleinen Controller und Fusion lassen sich dynamische Seiten in Neos vollständig ohne Fluid umsetzen. Der Controller lädt nur die Daten. Fusion übernimmt Layout, Inhalte und SEO-Links.

So lassen sich eigene URLs, mehrsprachige Inhalte und dynamische Seiten wie Event-Detailseiten sauber mit Neos umsetzen.