Migration steps

It is recommended to perform a Composer migration using the latest TYPO3 major release to prevent bugs and issues that have been solved in newer versions. If you are using an older TYPO3 version in Legacy installation mode, you have two options:

  • Upgrade TYPO3 Legacy first, then migrate to Composer. This is probably more straight-forward as you can follow the Legacy Upgrade Guide, and then this guide.
  • Migrate the old TYPO3 version to Composer first, then perform a major upgrade. This might be a bit tricky, because you have to use older versions of typo3/cms-composer-installers and dependencies like helhum/typo3-console, or outdated extensions on Packagist. You will need to read through older versions of this guide that match your TYPO3 version (use the version selector of the documentation).

Delete files

Make a backup first! If things go wrong, you can at least go back to the old version. You need a backup of

  • all files of your TYPO3 installation (by using FTP, SCP, rsync, or any other method)
  • the database (by exporting the database to an SQL file)

Also, you may prefer to upgrade a copy of your site first, if there have been a lot of changes and some of them might interfere with functions of your site. See the changelog to check that.

For more detailed information about TYPO3 backups see Backup strategy in TYPO3 Explained.

Yes, it's true that you will have to delete some files, because they will be newly created by Composer in some of the next steps.

You will have to delete public/index.php, public/typo3/ and any extensions that you have downloaded from the TYPO3 Extension Repository (TER) or other resources like GitHub in public/typo3conf/ext/. Also, delete your own custom extensions if they are published in a separate Git repository or included as a Git submodule.

Only keep your sitepackage extension and extensions which have been explicitly built for your current project and do not have their own Git repository.

Configure Composer

Create a file named composer.json in your project root (not in your web root).

You can use the composer.json file from typo3/cms-base-distribution as an example. Use the file from the branch which matches your current version, for example 12.x.

However, this file may require extensions you don't need or omit extensions you do need, so be sure to update the required extensions as described in the next sections.

Other ways of creating the composer.json file are via a composer init command, the TYPO3 Composer Helper or advanced project builders like CPS-IT project-builder which use a guided approach to create the file.

Add all required packages to your project

You can add all your required packages with the Composer command composer require. The full syntax is:

typo3_root$
composer require anyvendorname/anypackagename:version
Copied!

Example:

typo3_root$
composer require "typo3/minimal:^12"
Copied!

This uses the Packagist repository by default, which is the de-facto standard for Composer packages.

Composer packages follow a concept called SemVer <https://semver.org/ (semantic versioning). This splits version numbers into three parts:

  • Major version (1.x.x)
  • Minor version (x.1.x)
  • Patch-level (x.x.1)

Major versions should include intentional breaking changes (like a new API, changed configuration directives, removed functionality).

New features are introduced in minor versions (unless it is breaking change).

Patch-level releases only fix bugs and security issues and should never add features or breaking changes.

These Composer version constraints allow you to continuously update your installed packages and get an expected outcome (no breaking changes or broken functionality).

There are different ways to define the version of the package you want to install. The most common syntaxes start with ^ (e.g. ^12.4) or with ~ (e.g. ~12.4.0). Full documentation can be found at https://getcomposer.org/doc/articles/versions.md

In short:

  • ^12.4 or ^12.4.0 tells Composer to add the newest package of version 12.\* with at least 12.4.0. When a package releases version 12.9.5, you would receive that version. Version 13.0.1 would not be fetched. So this allows any new minor or patch-level version, but not a new major version.
  • ~12.4.0 tells Composer to add the newest package of version 12.4.\* with at least 12.4.0, but not version 12.5.0 or 13.0.1. This would only fetch newer patch-level versions of a package.

You have to decide which syntax best fits your needs.

This applies to TYPO3 Core packages, extension packages and dependencies unrelated to TYPO3.

As a first step, you should only pick the TYPO3 Core extensions to ensure your setup works, and add third-party dependencies later.

Install the Core

Once the composer.json is updated, install additional system extensions:

typo3_root$
composer require typo3/minimal:^12.4
composer require typo3/cms-scheduler:^12.4
composer require ...
Copied!

Or, in one line:

typo3_root$
composer require typo3/minimal:^12.4 typo3/cms-scheduler:^12.4 ...
Copied!

To find the correct package names, either take a look in the composer.json of that system extension or follow the naming convention typo3/cms-<extension name with dash "-" instead of underscore "_">, e.g. typo3/cms-fluid-styled-content. You can also go to Packagist and search for typo3/cms- to see all listed packages.

Install extensions from Packagist

You know the TYPO3 Extension Repository (TER) and have used it to install extensions? Fine. However, with Composer the required way is now to install extensions directly from Packagist.

This is the usual method for most extensions used today. Alternatively, some extension authors and commercial providers offer a custom Composer repository that you can use (see below). Installation is the same - composer require.

To install a TYPO3 extension you need to know the package name. There are multiple ways to find it out:

Notice on extension's TER page

Extension maintainers can link their TYPO3 extension in TER with the Composer package name on Packagist. Most maintainers have done this and if you search for the extension in TER you will see which command and Composer package name can be used to install the extension.

Search on Packagist

Packagist has a quick and flexible search function. Often you can search by TYPO3 extension key or name of the extension and you will most likely find the package you are looking for.

Check manually

This is the most exhausting way - but it will work, even if the extension maintainer has not explicitly provided the command.

  1. Search for and open the extension you want to install, in TER.
  2. Click button "Take a look into the code".

  3. Open file composer.json.

  4. Search for line with property "name". Its value should be formatted like vendor/package.

  5. Check if the package can be found on Packagist.

Example: To install the mask extension version 8.3.*, type:

typo3_root$
composer require mask/mask:~8.3.0
Copied!

Install extension from version control system (e.g. GitHub, Gitlab, ...)

In some cases, you will have to install a TYPO3 extension that is not available on Packagist or TER. For example:

  • a non-public extension only used in your company.
  • you forked and modified an existing extension.
  • commercial plugin / licensed download / Early Access (EAP)

As a first step, define the repository in the repositories section of your composer.json. In this example the additional lines are added to the top of composer.json:

/composer.json
{
    "repositories": [
        {
            "type": "vcs",
            "url": "https://github.com/foo/bar.git"
        }
    ],
    "extra": {
        "typo3/cms": {
            "web-dir": "public"
        }
    }
}
Copied!

Ideally, you should not edit a composer.json file manually, but instead use Composer commands to make the changes, like this:

typo3_root$
composer config repositories.foo-bar vcs https://github.com/foo/bar.git
Copied!

The Git repository must point to a TYPO3 extension with a composer.json.

See composer.json for details on what these files should look like.

Git tags in the repository are used as version numbers.

Instead of adding a single Git repository, it is also possible to add Composer repositories that aggregate multiple packages through tools like Satis, or Private Packagist repositories.

If these requirements are fulfilled, you can add your extension in the normal way:

typo3_root$
composer require foo/bar:~1.0.0
Copied!

Include individual extensions like site packages

A project will often contain custom extensions, such as a sitepackage which provides TYPO3-related project templates and configuration.

Before TYPO3 v12, these extensions were stored in the typo3conf directory typo3conf/ext/my_sitepackage. Composer mode allows you to easily add a custom repository to your project by using the path type. This means you can require your local sitepackage as if it was a normal package without publishing it to a repository like GitHub or on Packagist.

Usually these extensions are in a directory like <project_root>/packages/ or <project_root>/extensions/ (and no longer in typo3conf/ext/), so you would use:

typo3_root$
composer config repositories.local_packages path './packages/*'
composer require myvendor/sitepackage
Copied!

Your sitepackage needs to be contained in its own directory like <project_root>/packages/my_sitepackage/ and provide a composer.json file in that directory. The composer.json file needs to list all the possible autoloading information for PHP classes that your sitepackage uses:

EXT:my_sitepackage/composer.json
{
     "autoload": {
         "psr-4": {
             "MyVendor\\Sitepackage\\": "Classes/"
         }
     }
}
Copied!

Directory locations are always relative to where the extension-specific composer.json is stored.

Do not mix up the project-specific composer.json file with the package-specific composer.json file. Autoloading information is specific to an extension, so it is not usually listed in the project file.

Now our example project's composer.json would look like this:

typo3_root/composer.json
{
    "repositories": [
        {
            "type": "vcs",
            "url": "https://github.com/foo/bar.git"
        },
        {
            "type": "path",
            "url": "./packages/*"
        },
    ],
    "extra": {
        "typo3/cms": {
            "web-dir": "public"
        }
    }
}
Copied!

After adding or changing paths in the autoload section you should run composer dumpautoload. This command will re-generate the autoload information and should be run anytime you add new paths to the autoload section in the composer.json.

After all custom extensions have been moved out of typo3conf/ext/ you can delete the directory from your project. You may also want to adapt your .gitignore file to remove any entries related to that old directory.

New file locations

Finally, some files will need to be moved because the location will have changed for your site since moving to Composer.

The files listed below are internal files that should not be exposed to the webserver, so they are should be moved outside the public/ structure.

At a minimum, the site configuration and the translations should be moved.

Move files:

typo3_root$
mv public/typo3conf/sites config/sites
mv public/typo3temp/var var
mv public/typo3conf/l10n var/labels
Copied!

These locations have changed. Note that TYPO3 v12+ moved more configuration files to a new directory than TYPO3 v11:

Before After
public/typo3conf/sites config/sites
public/typo3temp/var var
public/typo3conf/l10n var/labels
public/typo3conf/LocalConfiguration.php config/system/settings.php
public/typo3conf/AdditionalConfiguration.php config/system/additional.php
public/typo3conf/system/settings.php config/system/settings.php
public/typo3conf/system/additional.php config/system/additional.php
public/typo3 vendor/typo3/
public/typo3conf/PackageStates.php removed
public/typo3conf/ext removed (replaced by vendor and e.g. packages)
public/typo3conf/ext/.../Resources/Public public/_assets (new)

The directory public/_assets/ and how to migrate public web assets from extensions and your sitepackage is described in: Migrating and accessing public web assets from typo3conf/ext/ to public/_assets .

Have a look at Directory structure in "TYPO3 Explained". Developers should also be familiar with the Environment API.