Skip to main content

Upgrading to 2.0

This guide covers upgrading a Sloth 1.x project to Sloth 2.0.

Automated upgrade with folivoro/climb

The fastest way to upgrade is with folivoro/climb — a dedicated migration tool that handles the upgrade automatically.

composer global require folivoro/climb

Make sure ~/.composer/vendor/bin is in your $PATH:

export PATH="$PATH:$HOME/.composer/vendor/bin"

Then from the root of your project:

climb

climb detects the installed Sloth version automatically and runs all migration steps. See the report at the end for anything that requires manual attention.


Manual upgrade

If you prefer to upgrade manually — or want to understand what climb does under the hood — follow these steps in order.

1. Update composer.json

Remove the Installer scripts — they are no-ops in v2 and can be safely deleted:

- "post-install-cmd": [
- "Sloth\\Installer\\Installer::config"
- ],
- "post-update-cmd": [
- "Sloth\\Installer\\Installer::config"
- ]

Swap the package:

composer remove sixmonkey/sloth
composer require folivoro/sloth:^2.0

Install folivoro/cecropia — the MU-plugin that bootstraps Sloth v2:

composer require folivoro/cecropia

If you use Layotter, install the bridge package:

composer require folivoro/layotter-bridge

And remove any old Layotter packages:

composer remove folivoro/layotter

2. Migrate config files

In v2, all configuration moves from Configure::write() calls to Laravel-style config files. Publish the defaults first:

wp sloth vendor:publish --tag=config

Then migrate each key. The full mapping:

Old (Configure::write)New (config/)File
twig.autoescapeview.autoescapeconfig/view.php
theme.twig.filtersUse View Extensions
theme.twig.functionsUse View Extensions
theme.image-sizestheme.image_sizesconfig/theme.php
theme.menustheme.menusconfig/theme.php
theme.routesUse Routes
theme.layotter.row_layoutslayotter.row_layoutsconfig/layotter.php
layotter_prepare_fieldslayotter.prepare_fieldsconfig/layotter.php
layotter_custom_classeslayotter.custom_classesconfig/layotter.php
autosync_acfNo longer part of Sloth
sloth.acf.processtheme.process_acfconfig/theme.php
urls.relativeapp.relative_urlsconfig/app.php
links.urls.relativeapp.relative_linksconfig/app.php
uploads.urls.relativeapp.relative_uploadsconfig/app.php
wp-json.baseUrlapp.wp_json.base_urlconfig/app.php
core.hide_updatesadmin.hide_updates.coreconfig/admin.php
plugins.hide_updatesadmin.hide_updates.pluginsconfig/admin.php
themes.hide_updatesadmin.hide_updates.themesconfig/admin.php
plugins.autoactivateNo longer part of Sloth
plugins.autoactivate.blacklistNo longer part of Sloth

Before:

Configure::write('theme.menus', [
'primary' => 'Primary Navigation',
'footer' => 'Footer Navigation',
]);

Configure::write('theme.image-sizes', [
'hero' => [1920, 1080, true],
]);

Configure::write('urls.relative', true);

After:

// config/theme.php
return [
'menus' => [
'primary' => 'Primary Navigation',
'footer' => 'Footer Navigation',
],
'image_sizes' => [
'hero' => [1920, 1080, true],
],
];

// config/app.php
return [
'relative_urls' => true,
];

3. Migrate Twig filters and functions

Configure::write('theme.twig.filters', [...]) and Configure::write('theme.twig.functions', [...]) are replaced by the View Extension system. Each filter or function becomes a class in theme/Extensions/View/:

// Before
Configure::write('theme.twig.filters', [
new TwigFilter('obfuscate_email', function($email) {
return str_replace('@', '[at]', $email);
}),
]);

// After — theme/Extensions/View/ObfuscateEmailHelper.php
class ObfuscateEmailHelper extends \Sloth\View\Extensions\AbstractViewExtension
{
public function getHelpers(): array
{
return [
'obfuscate_email' => fn($email) => str_replace('@', '[at]', $email),
];
}
}

4. Migrate theme supports

add_theme_support() calls in functions.php move to config/theme.php:

// Before — functions.php
add_action('after_setup_theme', function() {
add_theme_support('title-tag');
add_theme_support('post-thumbnails');
});

// After — config/theme.php
return [
'supports' => [
'title-tag',
'post-thumbnails',
],
];

5. Fix typed properties

PHP 8.4 raises a fatal error when a child class redeclares a property with a type that the parent (Corcel) declared without one. Remove type declarations from registration properties in your Models and Taxonomies:

// Before — fatal in PHP 8.4
class Project extends Model
{
public static string $postType = 'project';
public static array $names = ['singular' => 'Project', 'plural' => 'Projects'];
}

// After
class Project extends Model
{
public static $postType = 'project';
public static $names = ['singular' => 'Project', 'plural' => 'Projects'];
}

This affects $postType, $names, $labels, $options, $icon and any other static properties inherited from Sloth's base classes.

6. Clean up bootstrap.php

Remove Sloth v1 bootstrapping from bootstrap.php:

- use Sloth\Core\Sloth;
- $GLOBALS['sloth'] = Sloth::getInstance();
- class_alias('\Sloth\Configure\Configure', 'Configure');
- Configure::boot();

Everything else in bootstrap.php (constants, Dotenv, DB settings) can stay.

7. Delete sloth.php

The sloth.php MU-plugin that bootstrapped Sloth v1 is replaced by folivoro/cecropia in v2. Delete it from your MU-plugins directory.

8. Track infrastructure files in Git

In v1, Sloth's Installer managed bootstrap.php and wp-config.php and they were typically gitignored. In v2 these files are fully owned by your project and should be committed.

Remove them from .gitignore:

- bootstrap.php
- wp-config.php
- sloth.php

9. Update the .env location

Sloth now walks up from the App-Root to find .env. In Classic mode, .env should live next to composer.json in the project root — not inside app/:

# Classic mode
my-project/
├── .env ← here
├── composer.json
└── app/

# Theme mode — unchanged
my-theme/
├── .env
└── composer.json

Package rename

If your project still requires sixmonkey/sloth, update it:

composer remove sixmonkey/sloth
composer require folivoro/sloth:^2.0

Removed features

These features were removed in 2.0 with no replacement:

FeatureAlternative
Configure classconfig() and Laravel config files
theme.routes configSloth routing
plugins.autoactivate configManage plugins manually
autosync_acf configNo longer part of Sloth
Sloth InstallerNot needed — remove from Composer scripts
LayotterBridgeServiceProvidercomposer require folivoro/layotter-bridge