.. _page-rendering:

================
Rendering A Page
================

This section explains how pages are rendered in Neos. More precisely, we show how to render a node of type
``Neos.Neos:Document``. The default page type in Neos (``Neos.NodeTypes:Page``) inherits from this type.
If you create custom document node types, they need to be a subtype of ``Neos.Neos:Document`` as well.
This section also explains how to implement custom rendering for your own document node types.


.. figure:: data:image/png;base64, 
      :alt: Rendering flow example

.. HINT: To edit the image above, go to the URL below.
   The image is encoded in the URL itself, so make sure to update this URL as well once you're done. A new data url can
   be generated in draw.io by using "File>Embed>Image", the URL below is generated via "File>Publish>Link".
   https://www.draw.io/?lightbox=1&highlight=0000ff&edit=_blank&layers=1&nav=1&title=Untitled%20Diagram.xml#R3VdNj5swEP013MEGklybze4ednvYtOrZhVlwaxjkmCX019dgOwS5W1WqBMpyQPbzeD4ez9YQ0H11fpCsKZ8xBxGQMD8H9C4gZLOJ9XsAegMkYWiAQvLcQNEEHPkvsKAza3kOp5mhQhSKN3Mww7qGTM0wJiV2c7NXFPOoDSvAA44ZEz76jeeqNOiWbCb8EXhRushRujMr31n2s5DY1jZeQOjr%2BJjlijlfttBTyXLsriB6COheIiozqs57EAO1jjaz7%2F6d1UveEmr1LxtSs%2BGNiRZcxmNeqndcQK6psVOUqsQCayYOE%2FpprBcGj6GelaoSehjp4Q9Qqrdfl7UKNTR5eEJsrJ2JOQR6twwLnbCVmbWyqSomC7BW9EKhViZgBUr22kSCYIq%2Fzb0zq5HiYjfxpAeWqj%2FTRjzavr48ecxNvAxFdiVXcGzYmH6nj82cK%2BsRpILz31nw63MbrKj6%2BbSbFBw53ZVX6k3D%2Fydkc8M6or6O4oV0RD3a7jBrqyFbEn7Wt%2Br6mkrpaqLa3rCoYl9UyUKiij3a7tsTx3p1LdEoWU1LLtZNiinxxbRbSExR9LF4W%2BpmT%2FxDKHRTu%2FoZjNPtamdw53HyArp4qcsn4eOX5%2FU7qJQs1kLp6dTmj2tXv1L08Bs%3D

1. An URL is requested from Neos through an HTTP request.
2. The requested URL is resolved to a node. This works via the Frontend ``NodeController`` and the ``NodeConverter``
   of the Neos CR by translating the URL path to a node path, and then finding the node with this path. The document
   node resolution is completely done in the Neos core - usually, site integrators do not need to modify it.
3. The document node is passed to Fusion, which is the Neos rendering engine. Rendering always starts at the Fusion
   path ``root``. This rendering process is explained in detail below.
4. Fusion can render Fluid templates, which in turn can call Fusion again to render parts of themselves. This can go
   back and forth multiple times, even recursively.
5. Once Fusion has traversed the rendering tree fully, rendering is done and the rendered output (usually HTML, but
   Fusion can render arbitrary text formats) is sent back to the requester.


The ``root`` path
=================

You may already have seen a ``Root.fusion`` that contain a path ``page`` which is filled with an object of type ``Neos.Neos:Page``.
Here, the ``Neos.Neos:Page`` Fusion object is assigned to the path ``page``, telling the system that the Fusion object
``Page`` is responsible for further rendering::

  page = Neos.Neos:Page {
    head {
      [...]
    }
    body {
      [...]
    }
  }

Let's investigate how this rendering process happens.
Fusion always starts rendering at the fusion path ``root``. You can verify this by simply replacing the code in your
``Root.fusion`` file with this snippet::

  root = "Hello World!"

All page rendering will disappear and only the words "Hello World" will be rendered by Neos.

Using the  ``page`` path is not the recommended way to render your document node types anymore. We encourage you to define a prototype named after your document node type extending ``Neos.Neos:Page``. Read :ref:`rendering-custom-page-types` for further details and how to achieve this.

The root ``Neos.Fusion:Case`` object
====================================

The ``root`` path contains, by default, a ``Neos.Fusion:Case`` object. Here is a section from this object - to see the full implementation, check out the file ``DefaultFusion.fusion`` in the package ``Neos.Neos``, path ``Resources\Private\Fusion``. ::

  root = Neos.Fusion:Case {

    [...more matchers before...]

    documentType {
      condition = Neos.Fusion:CanRender {
        type = ${q(documentNode).property('_nodeType.name')}
      }
      type = ${q(documentNode).property('_nodeType.name')}
    }

    default {
      condition = TRUE
      renderPath = '/page'
    }
  }

If you do not know what a ``Case`` object does, you might want to have a look at the :ref:`neos-Fusion-reference`.
All paths in the ``Case`` object (so-called *matchers*) check a certain condition - the ``condition`` path in the matcher.
Matchers are evaluated one after another, until one condition evaluates to ``TRUE``. If it does, matcher's ``type``,
``renderer`` or ``renderPath`` path (whichever exists) will be evaluated. If no other condition matches, the ``default``
matcher is evaluated and points Fusion to the path ``page``. Rendering then continues with the ``page`` path, which is
by default generated in your site package's ``Root.fusion`` file. This is why, if you don't do anything else, rendering
begins at your ``page`` path.

The current best practice is to use the ``documentType`` matcher by defining your own Fusion prototypes for each document
type. This approach will be covered further below.

The page path and ``Neos.Neos:Page`` object
===========================================

The minimally needed Fusion for rendering a page looks as follows::

  page = Page {
    body {
      templatePath = 'resource://My.Package/Private/Templates/PageTemplate.html'
    }
  }


``Page`` expects one parameter to be set: The path of the Fluid template which is rendered inside the ``<body>`` of the
resulting HTML page.

If the template above is an empty file, the output shows how minimal Neos impacts the generated markup::

  <!DOCTYPE html>
  <html>
    <!--
        This website is powered by Neos, the Open Source Content Application Platform licensed under the GNU/GPL.
        Neos is based on Flow, a powerful PHP application framework licensed under the MIT license.

        More information and contribution opportunities at https://www.neos.io
    -->
    <head>
      <meta charset="UTF-8" />
    </head>
    <body>
      <script src="/_Resources/Static/Packages/Neos.Neos/JavaScript/LastVisitedNode.js" data-neos-node="a319a653-ef38-448d-9d19-0894299068aa"></script>
    </body>
  </html>

It becomes clear that Neos gives as much control over the markup as possible to the integrator: No body markup, no
styles, only little Javascript to record the last visited page to redirect back to it after logging in. Except for
the charset meta tag nothing related to the content is output by default.

If the template file is filled with the following content::

  <h1>{title}</h1>

the body would contain a heading to output the title of the current page::

  <body>
    <h1>My first page</h1>
  </body>

Again, no added CSS classes, no wraps. Why ``{title}`` outputs the page title is covered in detail below.

Adding pre-rendered output to the page template
-----------------------------------------------

Of course the current template is still quite boring; it does not show any content or any menu. In order to change that,
the Fluid template is adjusted as follows::

  {namespace fusion=Neos\Fusion\ViewHelpers}
  {parts.menu -> f:format.raw()}
  <h1>{title}</h1>
  {content.main -> f:format.raw()}

Placeholders for the menu and the content have been added. Because the ``parts.menu`` and ``content.main`` refer to a
rendered Fusion path, the output needs to be passed through the ``f:format.raw()`` ViewHelper. The Fusion needs to be
adjusted as well::

  page = Neos.Neos:Page {
    body {
      templatePath = 'resource://My.Package/Private/Templates/PageTemplate.html'

      parts {
        menu = Neos.Neos:Menu
      }

      content {
        main = Neos.Neos:PrimaryContent {
          nodePath = 'main'
        }
      }
    }
  }

In the above Fusion, a Fusion object at ``page.body.parts.menu`` is defined to be of type ``Neos.Neos:Menu``.
It is exactly this Fusion object which is rendered, by specifying its relative path inside
``{parts.menu -> f:format.raw()}``.

Furthermore, the ``Neos.Neos:PrimaryContent`` Fusion object is used to render a Neos ContentRepository
``ContentCollection`` node. Through the ``nodePath`` property, the name of the Neos ContentRepository
``ContentCollection`` node to render is specified. As a result, the web page now contains a menu and the contents
of the main content collection.

The use of ``content`` and ``parts`` here is **just a convention**, the names can be
chosen freely. In the example ``content`` is used for the section where content is later
placed, and ``parts`` is for anything that is not *content* in the sense that it
will directly be edited in the content module of Neos.

The ``Neos.Neos:Page`` object in more detail
--------------------------------------------

To understand what the ``Neos.Neos:Page`` object actually does, it makes sense to look at its definition. We can find the
``Page`` prototype in the file ``Page.fusion`` in the path ``Resources\Private\Fusion`` inside the ``Neos.Neos``
package. Here is a snippet taken from this object's definition::

  prototype(Neos.Neos:Page) < prototype(Neos.Fusion:Http.Message) {

    # The content of the head tag, integrators can add their own head content in this array.
    head = Neos.Fusion:Array {
      # Link tags for stylesheets in the head should go here
      stylesheets = Neos.Fusion:Array

      # Script includes in the head should go here
      javascripts = Neos.Fusion:Array {
        @position = 'after stylesheets'
      }
    }

    # Content of the body tag. To be defined by the integrator.
    body = Neos.Fusion:Template {
      node = ${node}
      site = ${site}

      # Script includes before the closing body tag should go here
      javascripts = Neos.Fusion:Array

      # This processor appends the rendered javascripts Array to the rendered template
      @process.appendJavaScripts = ${value + this.javascripts}
    }
  }

By looking at this definition, we understand a bit more about how page rendering actually works. ``Neos.Neos:Page``
inherits from ``Neos.Fusion:Http.Message``, which in turn inherits from ``Neos.Fusion:Array``. ``Array`` fusion objects
just render their keys one after another, so the Page object just outputs whatever is in it. The ``Neos.Neos:Page`` object
renders the HTML framework, such as doctype, head and body tags, and also defines the default integration points for
site integrators - ``head`` and ``body`` as well as their inner objects. It is not by coincidence that these exact paths
are pre-filled with sensible defaults in site package's generated default ``Root.fusion`` files.

We can also see that the ``body`` object is a ``Neos.Fusion:Template``, which is why we have to set the template path
to a Fluid template which will be rendered as the body.

Rendering custom document types
===============================

There are two basic approaches to render different document types. We currently recommend to create a Fusion
prototype per custom page type, which is since Neos 4.0 automatically picked up by Neos (see below). The "old" way
involves adding one root matcher per document type, explicitly checking for the node type in the condition, and
redirecting Fusion to another render path. It is documented here for completeness' sake, but we do not recommend to use
it anymore.

Prototype-based rendering
-------------------------

Since Neos 4.0, the root ``Case`` object ships with a ``documentType`` matcher, which will automatically pick up and
render Fusion prototypes with the same name as the corresponding document node type, if they exist. This snippet
of Fusion in the root ``Case`` is responsible for it::

  root = Neos.Fusion:Case {

    [...]

    documentType {
      condition = Neos.Fusion:CanRender {
        type = ${q(documentNode).property('_nodeType.name')}
      }
      type = ${q(documentNode).property('_nodeType.name')}
    }

    [...]
  }

This means that if you have a custom page type ``Your.Site:CustomPage``, you simply have to create a Fusion prototype
with a matching name to get different rendering for it. We explain how to do this in more detail in the "How To" section
of the docs: :ref:`rendering-custom-page-types`

Explicit path rendering (discouraged)
-------------------------------------

Before document-based rendering, you had to add your own matchers to the root object to get different rendering::

  root.customPageType1 {
    condition = ${q(node).is('[instanceof Your.Site:CustomPage]')}
    renderPath = '/custom1'
  }

  custom1 < page
  custom1 {
    # output modified here...
  }

There are a number of disadvantages of doing this, which is why we recommend to stick to prototype-based rendering:

* We are polluting the ``root`` namespace, adding to the danger of path collision
* We need to copy and modify the ``page`` object for each new document type, which becomes messy
* The order of path copying is important, therefore introducing possibly unwanted side effects

Further Reading
===============

Details on how Fusion works and can be used can be found in the section :ref:`inside-fusion`.
:ref:`adjusting-output` shows how page, menu and content markup can be adjusted freely.
