Dating Fluid Powered TYPO3

A once in a decade escapade — first steps into a post-TemplaVoila! era?

While developing this website, I had the chance to explore a lot of new techniques. This is going to be the first of a series of posts which I’ll use to record what I’ve learnt. Let’s begin with the probably most fundamental technical decision regarding this website: Retiring TemplaVoila! and going for Fluid Powered TYPO3 as templating system. This is not an expert article — read on for a noob’s first steps with FluidTYPO3.

Tinkering with your personal website is a pretty good chance to do all those exciting things your clients never ask you for — either because they don’t want to pay for these efforts or simply don’t value them. When I started working on my own portfolio, I wanted to put into practice as many as possible of those techniques that I’m personally keen on. It turned out that there are quite a lot of them. ツ

Old habits die hard

Whenever it comes to building a website, we at tollwerk will reach out for TYPO3 as CMS. We are doing this for 11 years now. As a prerequisite, one of the first things we will always install is TemplaVoila! as templating system. Always. We never did anything else, beginning with our very first TYPO3 site. We never employed the TYPO3 standard way of templating and started right away with what was called “futuristic template building” back in 2003.

In last November, I met Jonas Jabari, a young and enthusiastic Nuremberg based developer, who was full of praise for Fluid Powered TYPO3. He not only highly recommended giving it a try, but also kindly gave us an introduction to it — which saved me a lot of trial and error, as I know in the meantime. The first impression was good, so even without being fully convinced that the extension family formerly known as Fluid Extbase Development Framework (fed) would suffice all my needs, I decided to go for it and use it for my personal site. There wasn't much to lose, as this was not a typical client project with a tough timeline and a small budget.

On a side note, now that the further development of TemplaVoila! has been abandoned, I considered this a good occasion to check out FluidTYPO3 as a potential successor and try it on a manageable project without notable pressure and the risk of screwing up a critical client project.

Switching to Fluid powered TYPO3

The number one project goal was to develop a new blog extension that suited my needs. In the past, we used a custom extension for a couple of sites, but I was discontent and wanted to improve it in several ways. Most importantly, I always hated the fact that there was no usable preview of the blog posts in the backend. We used inline content elements (IRRE) for the article content, which totally sucked big time in every respect, but was still this was the most flexible approach regarding the content itself. For the future, however, I wanted to have a nice backend preview with drag and drop functionality for the content elements and at least some decent similarity with the frontend display.

Choosing FluidTYPO3 turned out to be the right decision for my objectives, although it took me quite some time to fully understand the relationship between the many different extensions. I ended up using these ones:

  • flux serves as a base extension on which all the others are depending. It brings Fluid based Flexforms to TYPO3. If you’re like me, you will probably wonder what’s the point in having a third method of laying out backend forms (besides TCA and Flexform XML). The answer is simple: Within the FluidTYPO3 ecosystem, Fluid as a language is the common denominator for a lot of tasks, not only — but also — for controlling backend forms. Read on for picking up more pieces of the puzzle.
  • I’m also using fluidpages, which brings Fluid based page templates to TYPO3. Compared to TemplaVoila!, building a page template is a lot easier with fluidpages: Instead of having a combination of an HTML skeleton, a template object record and an XML data structure, there’s only one single Fluid template file controlling all the aspects of your page. Nice one! I’ll give an example below.
  • Then there’s fluidcontent as the Fluid based content element counterpart to fluidpages. It replaces TemplaVoila!’s Flexible Content Elements (FCE) by — again — keeping all the aspects of a content element within one single Fluid template file. See below for an example.
  • Finally, the vhs extension provides a very comprehensive library of useful view helpers. If I am not mistaken, you can also use it for your projects independently from all the other extensions — definitely worth a closer look!

Without going into excessive detail, I’ll shortly highlight how the single extensions helped me to meet my targets. I’ll skip the extension bootstrapping part for now — FluidTYPO3 forces you to put all your efforts into a custom extension — and delve right into the single templates.

Building a blog post template

As I wanted to have a nice drag and drop enabled backend preview, I decided to use standard TYPO3 pages for my blog posts. In the past, we had always used a custom database table for the articles, so we were forced to edit them with the List module and never had a proper preview (of course we could have built a custom backend module around these records, but we did never did ...). Employing standard pages lets you just use the Page module for previewing your articles — that’s really easy and straightforward, and why reinvent the wheel?

Each blog article has some general attributes like a title, an abstract, an author, a banner image and so on. At the same time, each article consists of an arbitrary number of content elements of different types (like texts, images, citations, code blocks and so on), so it serves as a record container as well. With fluidpages, the configuration of the custom page attributes, their rendering in backend forms as well as the frontend output are controlled with the help of one single Fluid template. The following listing shows a simplified version of the template file used for this very page (look at the comments):

Raw code
{namespace flux=Tx_Flux_ViewHelpers}
 
<f:layout name="Page"/>
 
<div xmlns="http://www.w3.org/1999/xhtml" lang="en"
    xmlns:v="http://fedext.net/ns/vhs/ViewHelpers"
    xmlns:flux="http://fedext.net/ns/flux/ViewHelpers"
    xmlns:f="http://typo3.org/ns/fluid/ViewHelpers">
 
    <!-- Backend configuration -->
    <f:section name="Configuration">
 
        <!-- Custom configuration options in the page properties -->
        <flux:flexform id="pagestd" label="Standard page">
            <flux:flexform.field.select name="style" items="{0: {0: 'std', 1: 'Standard'}, 1: {0: 'blg', 1: 'Blog article'}}" requestUpdate="true"/>
            <flux:flexform.field.file name="preview" allowed="jpg,jpeg,png,gif" showThumbs="true"/>
            <flux:flexform.field.file name="banner.image" allowed="jpg,jpeg,png,gif" showThumbs="true"/>
            <f:if condition="{style} == 'blg'">
                <flux:flexform.field.select name="banner.type" items="{0: {0: 'ful', 1: 'Full width banner'}, 1: {0: 'inset', 1: 'Inset banner'}}" />
                <flux:flexform.field.input name="tags"/>
            </f:if>
        </flux:flexform>
 
        <!-- Display in the page backend module -->
        <flux:flexform.grid>
            <flux:flexform.grid.row>
                <flux:flexform.grid.column colPos="0" name="Page content" />
            </flux:flexform.grid.row>
        </flux:flexform.grid>
    </f:section>
 
    <!-- Frontend rendering -->
    <f:section name="Content">
        <main class="main {style}" role="main">
            <article class="h-entry" role="article">
                <header role="banner">
                    <!-- ... -->
                </header>
                <div class="e-content">
                    <!-- ... --->
                </div>
                <footer>
                    <!-- ... -->
                </footer>
            </article>
        </main>
    </f:section>
</div>

For each blog article, the <f:section name="Configuration"> element declares some general page attributes like

  • a rendering style,
  • a preview thumbnail or
  • the banner.image.

The flux namespace provides view helpers for defining and configuring fields of all the data types known from TCA. The <flux:flexform.grid> controls the layout in the page backend module, in this case by allocating one container column for content elements (which would map to a TemplaVoila! field of type “Page-Content Elements [Pos.: 0]”).

In the second part of the template, the <f:section name="Content"> contains the Fluid code which makes up the frontend rendering of the page (everything inside the <body> element). This is working just like a regular Extbase / Fluid template, with some additions:

  • The custom page attributes defined in the upper part of the template can be referenced directly with {style}, {preview}, {banner.image} and so on.
  • All the standard attributes of the page record can be accessed with the page prefix, e.g. {page.title}, {page.abstract} and so on.

Of course this was just a very rough introduction to fluidpages, but I'm sure you got the point: It’s pretty comfortable to have it all together in one single file, consistently written in Fluid, isn't it?

Custom content elements

When it came to the content elements for my blog posts, an important decision had to be made: Would I want to use the standard TYPO3 content elements, or would I rather create custom ones using fluidcontent? For several reasons I went for custom ones. Most importantly, while really seeing a point in sticking to the standard elements, using them would have required me to rewrite large parts of the frontend rendering TypoScript, as I’m generally not willing to accept that shitload of cruft coming with the default css_styled_content rendering.

Hey, pssst, TYPO3 guys! Just in case you missed it: It’s 2014 and the world went responsive! We don’t need immutably hardcoded width and height attributes on images any more, ok?!

For simple text sections, adjusting the frontend rendering might have been acceptable, but I also wanted to have some special elements and certain behaviour (like text floating around images), so creating a bunch of Fluid Content Elements with very lean code was the easier way in my situation. Unfortunately, the considerable downside of the flexibility gained by Fluid Content Elements is a serious data keeping problem — see the end of this article.

Just like with page templates, all aspects of a Fluid Content Element are kept within one single Fluid template file that simultaneously defines

  • the custom backend form fields provided by the element,
  • the element’s rendering in the page backend module — this is my beloved preview feature! ツ —, and finally
  • the frontend rendering of the element.

As an example, take look at the template of my custom image content element (for the sake of readability I simplified it a little and hardcoded the originally localized text labels):

Raw code
{namespace flux=Tx_Flux_ViewHelpers}
{namespace v=Tx_Vhs_ViewHelpers}
{namespace jkphl=Jkphl\JkphlBlog\ViewHelpers}
 
<f:layout name="Content" />
 
<div xmlns="http://www.w3.org/1999/xhtml"
     xmlns:flux="http://fedext.net/ns/flux/ViewHelpers"
     xmlns:v="http://fedext.net/ns/vhs/ViewHelpers"
     xmlns:f="http://typo3.org/ns/fluid/ViewHelpers">
 
    <!-- Custom configuration options -->
    <f:section name="Configuration">
        <flux:flexform wizardTab="Blog" id="image" icon="{v:extension.path.resources(path: 'Icons/fluidcontent/image.png')}" description="Adds an image with some positioning / text flow options">
            <flux:flexform.field.file name="image" allowed="jpg,jpeg,png,gif" showThumbs="true"/>
            <flux:flexform.field.text name="caption" enableRichText="true" defaultExtras="richtext[bold|italic|link]:rte_transform[flag=rte_enabled|mode=ts_css]" />
            <flux:flexform.field.select name="style" items="{0: {0: 'image-normal', 1: 'Normal image'}, 1: {0: 'image-half', 1: 'Half-width image'}, 2: {0: 'image-outset', 1: 'Outset half-width image'}}" />
            <flux:flexform.field.checkbox name="shadow"/>
        </flux:flexform>
    </f:section>
 
    <!-- Display in the page backend module -->
    <f:section name="Preview">
        <table style="border-collapse:collapse">
            <tr>
                <th width="120" style="padding:0" rowspan="3"><jkphl:backend.image src="{image}" width="110" alt="{caption}"/></th>
                <th width="60" style="padding:0">Caption</th>
                <td style="padding:0"><f:format.html>{caption}</f:format.html></td>
            </tr>
            <tr>
                <th width="100" style="padding:0">Style</th>
                <td style="padding:0"><f:translate key="LLL:EXT:jkphl_blog/Resources/Private/Language/locallang.xlf:flux.image.fields.style.{style}"/></td>
            </tr>
            <tr>
                <th width="100" style="padding:0">Cast shadow</th>
                <td style="padding:0">{f:if(condition: '{shadow}', then: 'v', else: '-')}</td>
            </tr>
        </table>
    </f:section>
 
    <!-- Frontend rendering -->
    <f:section name="Main">
        <figure id="section-{record.uid}" class="image {style}">
            <img src="{image}" alt="{f:format.stripTags(value: caption)}"{f:if(condition: '{shadow}', then: ' class="shadow"')}/>
            <f:if condition="{caption}">
                <figcaption><f:format.html>{caption}</f:format.html></figcaption>
            </f:if>
        </figure>
    </f:section>
 
</div>

Again, the template consists of three parts:

  • The first one defining the content element’s attributes to be set in backend forms,
  • the next one controlling the display in the page backend module,
  • and finally the last one making up the frontend rendering.

As you can see in the example, with fluidcontent you have a lot of control over the element’s preview in the page backend module — this is what I always wanted!

The preview rendering of content elements in the page backend module can freely be customized

The preview rendering of content elements in the page backend module can freely be customized

On a side note, did you notice the icon and description attributes of the <flux:flexform> element in the first part of the example? These are used for controlling the element’s appearance in the “New Content Element Wizard”:

Fluid content element appearance in the “New Content Element Wizard”

Fluid content element appearance in the “New Content Element Wizard”

Again, it is really very comfortable to have all the aspects of your content elements combined in a single place, packed into a well-structured and readable Fluid template, without the need of a scattered mix of HTML, TypoScript and PHP.

Pros & cons

As a personal conclusion, here is what I like most about FluidTYPO3:

  • First of all, it enables you — no, it forces you — to work very domain centric. As opposed to TemplaVoila!, it requires you to put all your components into a custom TYPO3 extension. What might seem odd at first is in fact a huge advantage in case you intend to reuse your page and content element templates in another TYPO3 installation: Simply install that extension there and you’re all set (almost at least)! But even if just stay within one TYPO3 instance, it really helps you to keep track of everything.
  • I also like the concept that every aspect of a particular entity — be it a page or a content element — is defined in a single file instead of being spread all over your file system and the database.
  • Without a doubt, Fluid is a really powerful templating language, and it just feels right to use it for the rendering of pages and content elements as well — now that Extbase has become the de facto standard for frontend plugin and backend module programming.
  • The whole FluidTYPO3 extension family is very actively maintained by a group of excellent developers. I was lucky enough get in contact with them for a couple of reasons, and they’ve been truly helpful all the time. Thanks Claus Due, Cedric ZielBjörn Fromme and Danilo Bürger!

On the other hand, there are some hiccups that might become problems under certain circumstances — in any case they deserve further improvement:

  • The FluidTYPO3 ecosystem is really, really huge and complex. Unfortunately, I have not been able to find a compact, simple and understandable documentation that gives a comprehensive overview across all the extensions and provides a conclusive step-by-step introduction. I really had a hard time finding the entrance — despite my 10+ years as a TYPO3 developer. Without the initial instructions from Jonas I’d probably have given up pretty soon (thanks again for that, Jonas!).
  • Unlike TemplaVoila!, FluidTYPO3 doesn't bring any shiny backend tools for defining or mapping templates on a visual basis. Everything has to be done by hand with a code editor inside the Fluid templates. While I am perfectly fine with this, the less experienced integrator might consider this an obstacle.
  • For particularly time and budget critical projects, the extension suite might still be a little bit too much “work in progress”. Right after I started, I had to spend a couple of hours just to figure out that some of the extensions available in the official TYPO3 extension repository (TER) simply didn’t work without flaws — at least not within our setup. Once I cloned the GitHub repositories, though, everything was just running fine. Some weeks later I updated the extension (again from GitHub) and my programming broke again in several places. I suspect this to be the downside of the very active development cycle, but I can live with it! ツ
  • Finally, there’s one thing that really keeps me very, very sceptic — and that’s not a problem of FluidTYPO3 itself: I’m talking about Flexforms. I never liked them. For my understanding, they are nothing more than an lame excuse for not doing the database right. Until further notice, I’ll simply avoid thinking about what I’m going to face when I once feel the need of implementing a search feature on this website. All the texts are buried in some non-normalized, imprecisely queryable XML database fields. Oh my god, what a mess! I conclude that, at this very moment, you should be very careful when considering which data to keep as a Fluid based attribute rather than a good old TCA column.

As a whole, I really enjoyed using FluidTYPO3 for the first time. It is definitely an adequate substitute (and more) for TemplaVoila!, and I’ll make sure that we’re going to use it for an increasing number of client projects in the future. Yet I wish that someone more experienced wrote some really good tutorials about it, and also the data keeping strategy should be rethought one day. In any case, I absolutely recommend having a look at it — FluidTYPO3 is well worth the try!