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.autoescape | view.autoescape | config/view.php |
theme.twig.filters | — | Use View Extensions |
theme.twig.functions | — | Use View Extensions |
theme.image-sizes | theme.image_sizes | config/theme.php |
theme.menus | theme.menus | config/theme.php |
theme.routes | — | Use Routes |
theme.layotter.row_layouts | layotter.row_layouts | config/layotter.php |
layotter_prepare_fields | layotter.prepare_fields | config/layotter.php |
layotter_custom_classes | layotter.custom_classes | config/layotter.php |
autosync_acf | — | No longer part of Sloth |
sloth.acf.process | theme.process_acf | config/theme.php |
urls.relative | app.relative_urls | config/app.php |
links.urls.relative | app.relative_links | config/app.php |
uploads.urls.relative | app.relative_uploads | config/app.php |
wp-json.baseUrl | app.wp_json.base_url | config/app.php |
core.hide_updates | admin.hide_updates.core | config/admin.php |
plugins.hide_updates | admin.hide_updates.plugins | config/admin.php |
themes.hide_updates | admin.hide_updates.themes | config/admin.php |
plugins.autoactivate | — | No longer part of Sloth |
plugins.autoactivate.blacklist | — | No 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:
| Feature | Alternative |
|---|---|
Configure class | config() and Laravel config files |
theme.routes config | Sloth routing |
plugins.autoactivate config | Manage plugins manually |
autosync_acf config | No longer part of Sloth |
| Sloth Installer | Not needed — remove from Composer scripts |
LayotterBridgeServiceProvider | composer require folivoro/layotter-bridge |