Contao Open Source CMS 6.0.0

Contao 6.0.0, a new version of the Contao open source CMS, has been released.

Whilst the new major release, Contao 6.0, may not be packed with new features for users, the core has been thoroughly overhauled and technically modernised. From now on, Contao will only use Twig templates and rely on output encoding. This has laid the necessary foundations for new features in future versions of the 6.0 series.

What’s gone?

Input encoding

Up until now, Contao has encoded input as soon as it is saved; for example, < was written to the database as &#60;. From Contao 6.0 onwards, all data remains in its raw form in the database and is only encoded and masked when it is output.

For day-to-day work in the back end, this does not change anything for the time being. However, it does make a significant difference for development and when outputting data in templates. From now on, the context in which the data is processed determines whether it may be output 1:1 (raw) or not. For example, something classified as unsafe in an HTML template may be unproblematic – or even desirable – when passed to an external interface. Particularly with externally connected systems, it is preferable for data to arrive in its raw form rather than having to be laboriously converted first.

In Twig, encoding and escaping protect the data when it is output in templates. By default, Twig uses UTF-8 and escapes HTML output to prevent cross-site scripting (XSS). However, if the |raw filter is used, you must check the data arriving there, as the protection no longer applies and no unchecked data must be output. It is recommended to avoid raw wherever possible and instead use sanitize_html('contao') so that only safe HTML tags are allowed through.

Moritz explained this topic wonderfully using an example in his presentation on output encoding. Furthermore, in his recap of the first Contao Core Developers Meeting 2026, Yanick describes in detail why input encoding is a problem. Both are well worth reading if you want to delve deeper into the subject.

When updating to Contao 6.0, Contao automatically handles the database migration. However, it is important that you update from the latest version of Contao 5.7 and that you have completed all pending migrations there beforehand.

HTML5 templates

A logical consequence of this is that, due to the switch to output encoding, support for HTML5 templates has been discontinued. So, to be absolutely clear: the old template system has been completely removed; Contao 6.0 works exclusively with Twig. Any templates with the .html5 extension will no longer work. This applies not only to the core, but also to all extensions.

The fe_page page layout is still supported. From now on, you can use the Twig version fe_page.html.twig for this. The switch to the new Twig page layouts with slots is therefore not mandatory; it is entirely up to you.

Back end themes

It is no longer possible to have multiple back end themes in Contao 6.0. The previous "flexible" theme becomes the default, and the system/themes folder is no longer used. If you wish to customise and adapt the back end, you should use your custom CSS and include it via an entry in the config/config.yaml file.

# config/config.yaml
contao:
    backend:
        custom_css:
            - files/backend/custom.css
        custom_js:
            - files/backend/custom.js

In your custom CSS, you can, for example, define your own colours or a logo. See also docs.contao.org.

BBCode

The Comments bundle no longer supports BBCode. This used to allow you to format the comment text, for example. Contao automatically converts existing comments to plain text during the update, so you don’t need to make any manual changes.

A lot of old code is being phased out

Contao 6.0 essentially removes the code associated with the old HTML5 template engine and its templates. This means that over 30,000 lines of legacy code are being removed from the core. This also highlights just what a colossal undertaking the core team has been managing on their own up to now. With Twig, Contao is now relying on an industry standard instead.

Other features marked as “deprecated” in Contao 5 are largely retained in Contao 6, provided they are not related to input encoding. This code will not be removed until Contao 7. This decision gives extension developers more time to make the necessary adjustments.

What’s different?

As well as the features that have been removed, there are also some that have been adapted or optimised.

insert_tag_raw becomes insert_tag_html

The Twig filter insert_tag_raw is now called insert_tag_html. The old name still works, but is deprecated.

The filter is now pre-escaped, so a raw must be placed before it. So foo|insert_tag_raw|raw becomes foo|raw|insert_tag_html.

New file hash in DBAFS

Contao now calculates file hashes using xxh128 instead of md5. This is noticeably faster, particularly when dealing with large numbers of files. For the update, this means: synchronise the file system completely beforehand so that the migration can rebuild the hashes correctly.

File insert tag with VFS support

The insert tag {{file::*}} now works with the virtual file system. This means it accesses the same level of abstraction as the rest of Contao and benefits from the additional capabilities.

In this context, all file handling has been migrated to the VFS. If you use the file insert tag or the download or video element for a file in the files directory that is not public, Contao now generates temporary URLs to the restricted files. This allows restricted files to be embedded directly for logged-in members, rather than simply being offered as downloads. For example, you can now stream a video from a restricted directory instead of simply making it available for download.

CSS classes for form fields

Contao now only applies custom CSS classes for form fields to the enclosing wrapper, and no longer applies them to each individual field within it. Please check your CSS in this regard if you have previously relied on the class being applied directly to the field.

Model values provide the default

If a value is missing, the model now returns the default value from the column definition instead of null. Furthermore, Contao casts the values to the database column type. This ensures more reliable return values and reduces the need for special handling in your own code.

Virtual fields

In addition to actual database fields, Contao has also supported virtual fields since version 5.7. The reason for this is a practical one: MySQL limits the row size per table. Anyone using a large number of extensions has previously hit this limit (keyword: "Row size too large") and been unable to create any further fields. With virtual fields, this no longer happens.

In Contao 6.0, the core itself now uses virtual fields for the first time for the video player element. For development purposes, the core also introduces a new AbstractColumnToVirtualMigration, which can be used to convert custom fields into virtual fields.

If you’d like to find out more about how virtual fields work, have a read of this section in the manual: docs.contao.org.

New features

As mentioned at the start, a major version release tends to focus less on new features. A few have been added nonetheless.

JSON-LD type for news items

For each news archive, you can now specify which JSON-LD type the posts should be assigned, for example NewsArticle. You’ll find this setting in the news archive’s advanced settings. The following options are currently available: NewsArticle, BlogPosting, Article. This enables search engines to categorise your content more accurately, which can have a positive effect on how it appears in search results.

Primary-Page-Image

In the page settings, you can now set a page image. Contao writes this image as primaryImageOfPage in the page’s JSON-LD data. This allows you to specify which image search engines should associate with the page. The image can now also be displayed in the Contao search results in the same way as the news image.

Incidentally, the image can also be used in the frontend if required, for example as a header image. To do this, add the relevant output to your Twig template. You can access it via contao.page.primaryImage. You can then use this to generate the image in the template:

{% set myimage = figure(contao.page.primaryImage|default, [1200, 500, 'crop']) %}

{% if myimage %}
    <div class="primary-image">
        {% with {figure: myimage} %}{{ block('figure_component') }}{% endwith %}
    </div>
{% endif %}

Insert into Nested Elements

You can now insert content elements directly into nested elements without first opening the element’s child view. This saves you a few clicks in the back end.

Simple-Token-Filter

With the new Twig filters simple_token and simple_token_html, Simple tokens are now replaced correctly in Twig templates. You can use Simple tokens in your newsletter, for example. You can find out more in the manual.

Dependencies

Before you update, do take a look at the technical requirements for Contao 6.0:

  • PHP: 8.4+
  • Symfony: 7.4 and 8
  • Monolog: 3
  • Doctrine DBAL: 4.4+
  • Doctrine ORM: 3.6

The update to Contao 6.0

If you want to update directly to Contao 6.0 now, there are a few important points you should bear in mind. I’ve already mentioned a few of these in the article, but here’s a summary of what you absolutely must pay attention to.

  1. Update from the latest Contao 5.7.x version. The database migrations are based on this. So first update to the latest 5.7 version and only then switch to 6.0.
  2. Run contao:filesync beforehand. The file hash changes to `xxh128`. So in Contao 5.7, you must synchronise the file system. After the update, carry out another synchronisation straight away.
  3. Convert all templates to Twig. The HTML5 templates will no longer work after the update. Switching to Twig is therefore mandatory. It’s best to carry out this work in good time whilst still on Contao 5.7.
  4. Read the UPGRADE.md file. It provides a comprehensive list of all changes and is essential reading for a major version update.

As always, remember to create a full backup before the update and ideally work on a copy!

We will publish a complete, detailed step-by-step guide for updating from Contao 5 to Contao 6 again with the next LTS version, Contao 6.3.

Should I upgrade now?

For most installations, we recommend waiting a little longer. It’s better to first ensure your installations are fully up to date with Contao 5.7 and to migrate all templates to Twig. This will allow you to complete the bulk of the groundwork whilst remaining on an LTS version with support until 2030.

What’s more, very few extensions have been released for Contao 6 so far. The extension developers also need to adapt their packages to the new encoding and to Twig first. As always, you can help by submitting pull requests where appropriate or by providing financial support.

Further information

The official release post on contao.org is also worth a read, and the Contao Academy’s YouTube video is well worth watching.

trakked is compatible with Contao 6.0
As usual, all the familiar features are available to you in trakked for Contao 6.0.

Changelog of the fixed issues in Contao 6.0.0:

Changelog of the fixed issues in Contao 6.0.0-RC2:

Changelog of the new features in Contao 6.0.0-RC1:

Changelog of the fixed issues in Contao 6.0.0-RC1:

About Contao 6.0

The first stable version of Contao 6.0 has been released on 26 August 2026 and will be the successor to Contao 5.7. 6.0 will be updated until 14 February 2027, after which it will be replaced by Contao 6.1.

Christian Feneberg

Christian takes care of marketing at trakked. You probably know Christian from television (Contao TV), together wth Dennis, he leads us through the Contao Show. He is the founder of the Contao Academy and loves to share his Contao knowledge, collected since 2010. He is also a big fan of automation. When time allows for it, he likes to spend his spare time with his family or reading a book about personal development.