Upgrade from 3.4 to 4.0

A guide for upgrading from 3.4 to 4.0. For most sites (those running Laravel > 8), the process will take less than 5 minutes.


First read through this guide to see if there's anything that you might need to adjust. While there are many items on this page, a majority of them only apply to addons or custom code. We've noted who each item would apply to so you can more easily scan through the changes.

Upgrade using Composer

In your composer.json, change the statamic/cms requirement:

"statamic/cms": "3.4.*"
"statamic/cms": "^4.0"

Then run:

composer update statamic/cms --with-dependencies

High impact changes

PHP and Laravel support

Affects apps using PHP < 8 or Laravel < 9.

  • The minimum version of PHP is now 8.0.
  • The minimum version of Laravel is now 9.

AMP has been removed

Affects apps using the AMP feature.

AMP is considered a dead project, and no longer provides SEO benefits, so the entire AMP feature has been removed.

API filters are opt-in

Affects apps using the GraphQL or REST API features.

All filters are disabled by default now for increased security. You must opt into each one you want made available.

// config/statamic/api.php or config/statamic/graphql.php
'resources' => [
'collections' => true,
'collections' => [
'blog' => [
'allowed_filters' => ['title', 'slug']

If you try to use a filter that has not been explicitly allowed, it will result in a validation error.

Medium impact changes

Route namespaces have been removed

Affects apps or addons using PHP-based routes.

When using the following various methods of adding custom routes, previously Statamic would assume a namespace. In 4.0, the namespace is removed.

Standard Laravel routes that you've added to your app routes files are not affected.

  • Statamic::pushCpRoutes()
  • Statamic::pushWebRoutes()
  • Statamic::pushActionRoutes()
  • Addon route files
  • Addon service provider $this->registerCpRoutes()
  • Addon service provider $this->registerWebRoutes()
  • Addon service provider $this->registerActionRoutes()

For example, in an addon's cp.php routes file:

Route::get('example', 'ExampleController@foo');
// v3 = Your\Addon\Http\Controllers\ExampleController@foo
// v4 = ExampleController@foo

In an addon, if you want a namespace, you can add one with a property:

protected $routeNamespace = 'Your\Addon\Http\Controllers';

However, we recommend using the class reference syntax:

use Your\Addon\Http\Controllers\ExampleController;
Route::get('example', [ExampleController::class, 'foo']);

Str::replace arguments changed

Affects apps or addons using Statamic\Support\Str::replace().

The Statamic\Support\Str::replace() method changed the argument order. The $subject argument moved from first to last.

Str::replace($subject, $search, $replace);
Str::replace($search, $replace, $subject);

Tailwind 3

Affects apps or addons with custom CP components.

The Control Panel has been upgraded from Tailwind 1 to 3. The sizing scale has been adjusted. Custom components may render unexpectedly and may need to have classes renamed.

Entry date behavior

Affects apps or addons with custom code.

When using the date method on an entry, an exception will be thrown if the entry is not in a dated collection.

Because of this, if you are creating an entry instance, you should set the collection before the date.

->set('foo', 'bar');

Low impact changes

Control Panel Composer actions have been removed

Affects users who are used to updating Statamic and addons using the Control Panel.

The ability to update Statamic, as well as installing and updating addons through the Control Panel has been removed. You will now need to use Composer on the command line.

The Control Panel sections remain, however the buttons will now give you the Composer commands rather than running them for you.

jQuery removed

Affects apps or addons with custom CP components using jQuery.
jQuery and jQuery UI were seldom used, and have been removed to lower the CP's overhead. We suggest replacing with Vue or Alpine equivalents.

vue-reactive-provide removed

Affects custom CP Vue components using the reactiveProvide property.

The vue-reactive-provide package was removed. We suggest using providing an observed object.

reactiveProvide: {
name: 'foo',
include: ['alfa', 'bravo']
provide: {
foo: this.foo
data() {
foo: this.makeProvidedFoo();
methods: {
makeProvidedFoo() {
const foo = {};
Object.defineProperties(grid, {
alfa: { get: () => this.alfa },
bravo: { get: () => this.bravo },
return foo;

Flysystem v1 support dropped

Affects apps or addons explicitly using Flysystem v1 code.

Support for league/flysystem v1 has been removed. Only v3 is supported.

CommonMark v1 support dropped

Affects apps or addons with custom CommonMark v1 extensions.

Support for league/commonmark v1 has been removed. Only v2 is supported.

Typography CSS styling

Affects apps or addons with custom CP components using the clean-content CSS class.

The custom .clean-content css class in the Control Panel has been replaced by .prose from Tailwind's typography plugin.

FontAwesome and Entypo fonts have been removed

Affects apps or addons with custom CP components using these fonts.

Both icon fonts have been removed, and replaced with Streamline SVG icons.

SortableList delay has been reduced to zero

Affects apps or addons with custom CP components using the SortableList component.

The delay was reduced from 200 to 0. The prop still exists, so you can manually bring it back.

<sortable-list :delay="200">

However, we suggest using a distance over delay in most cases.

<sortable-list :distance="10">

Panes have been removed

Affects apps or addons with custom CP components using the Pane component.

The "pane" feature has been removed. You can replace it with a narrow stack.

<stack narrow>
Some content

Color fieldtype has been simplified

Affects apps using the color fieldtype in their blueprints.

The color fieldtype now only supports hex values with no alpha channel.

PortalVue and vue-js-modal components have been renamed.

Affects apps or addons with custom CP components using the <portal> or <vue-modal> components.

Statamic v4 introduces our own <portal> component, so to prevent conflicts, the underlying PortalVue package's component has been renamed to <v-portal>.


For consistency, we renamed the underlying modal component from <vue-modal> to <v-modal>.

Docs feedback

Submit improvements, related content, or suggestions through Github.

Betterify this page →