🚚 How to migrate to Kirby Tips & tutorials
Skip to content
Next major version

Kirby 5 – alpha 4

Get a glimpse into the future at Kirby's next major release.

🧑‍💻 Disclaimers

We would love to get your feedback. Try out the alpha with a fresh Starterkit or locally with one of your projects. And help us find any bugs or regressions.

Have a look at the breaking changes. An important one: v5 will require PHP 8.2.

We recommend to not use this alpha version in a production project.

As we have switched to a new versioning scheme with Kirby 4, the next major release of Kirby will be v5 and is expected for the beginning of 2025. v5 behaves to v4 a lot more than e.g. 3.8 to 3.7. It won't be such a massive step as v3 to v4 and therefore even easier to upgrade.

We are sharing a the latest alpha with you. But please treat it for what it is: an alpha state. This means that this version is far from complete. More features will be added over the next few months, and other parts will change again.

Kirby 5 will be a free upgrade for everyone with a Kirby Basic or Enterprise license for Kirby 4. Our new licenses include three years of major updates.

🔥 Highlights

The changelog is getting longer and longer. Here are the highlights of this upcoming release:

Versions: Preview your changes

Editors can now make changes and get a full, rendered preview right from the Panel before they save them. Learn more ›

Dark theme: Turn off the Panel lights

As requested from many – whether as personal preference or for making the Panel more accessible with certain sight conditions – you are able to activate a dark theme for the Panel. Learn more ›

View buttons: Put your own button up there

Kirby 5 adds new extensions that allow plugin developers to add custom view buttons to most views of the Panel (e.g. page, site, file, user, language). Learn more ›

Chunked uploads: Bring out the big files

Kirby 5 supports large Panel uploads. Uploads are no longer restricted by the server's upload_max_filesize limit. Learn more ›

File previews: Your media at a glance

We're opening up the preview part of the Panel's file view to more rich media previews that aren't just images. Learn more ›


Let's dive deeper ...

🎉 Features

New in Alpha 1

Dark theme: Turn off the Panel lights

As requested from many – whether as personal preference or for making the Panel more accessible with certain sight conditions – you are able to activate a dark theme for the Panel from your account view in v5. #6299

We do expect to receive a lot of feedback on this feature and that the exact styling will be fine-tuned in the following pre-releases based on your feedback.

View buttons: Put your own button up there

Kirby 5 adds new extensions that allow plugin developers to add custom view buttons to most views of the Panel (e.g. page, site, file, user, language). These buttons can be added alongside the default buttons, such as the preview button or settings dropdown button. #6393

There are different ways to define a custom button: in a blueprint, in the config.php, in a Panel area or as a full custom Vue component.

In a blueprint

To select which buttons to show on a particular view you can set the buttons option in the corresponding blueprint:

site/blueprints/pages/note.yml
buttons:
  - preview
  - settings

This way, you can reference existing buttons by name and decide which ones to include and in what order.

A custom Vue component

Some custom buttons might need more options, more interactivity, more glamour than <k-view-button> offers. Those can create their own Vue component in your plugin's JavaScript file:

site/plugins/your-plugin/index.js
panel.plugin("getkirby/custom-view-buttons", {
  viewButtons: {
    applause: {
      template: `<k-button icon="heart" variant="filled" theme="love" size="sm" @click="applause">Applause</k-button>`,
      methods: {
        applause() {
          alert("👏");
        },
      },
    },
  },
});

You can then reference it by name in your blueprints or config file. Or if you want to pass props as well:

buttons:
  - preview
  - settings
  - applause
New in Alpha 2

Bring out the big files: Chunked uploads

Kirby 5 supports large Panel uploads. Uploads are no longer restricted by the server's upload_max_filesize limit but instead uploaded in chunks that are pieced back together on the server.

If you want to keep restricting the upload size to some limits, the file blueprint accept maxsize option is your friend.

Even Better View buttons

Building upon the foundation from Alpha 1, you can now also define new custom buttons directly in your blueprints:

buttons:
  - preview
  - settings
  myBytton:
    text: My Button
    link: https://getkirby.com
    theme: positive

You can also pass custom Vue component and its props.

buttons:
  - preview
  - settings
  applause:
    component: k-applause-view-button
    props:
      foo: bar

The available options are based on the k-view-button component (better docs will follow until the final release).

In the config.php

Similarly to the blueprints, buttons can now be defined in your config file. In this case, not for a specific template but in general for the different view types (page, file, site, user, system, ...):

site/config/config.php
'panel' => [
  'viewButtons' => [
    'site' => [
      'preview',
      'a' => [
        'icon'   => 'heart',
        'text'   => 'Kosmos',
        'theme'  => 'purple-icon',
        'target' => '_blank',
        'link'   => 'https://getkirby.com'
      ],
      'b-dropdown' => [
        'props' => [
          'icon'     => 'info',
          'text'     => 'Info',
          'dropdown' => 'my/dropdown/route'
        ]
      ],
      'c-component' => [
        'component' => 'my-custom-component',
        'props' => [
          'foo' => 'bar'
        ]
      ]
    ]
  ]
]

What you can see above are three different ways to define a custom button:

  • The first one directly defines the options. It's a shortcut that assumes these are the props for the k-view-button component.
  • In the second example, they are already wrapped inside the props key. But no component is defined, so k-view-button is used as well.
  • In the third example, we actually define a custom Vue component that should be used instead, alongside passing props to this component.

In a Panel area

If you do not want to define just one button via the config, but reuse it (or even ship it as part of your plugin), you can add them to the Panel area extension:

site/plugins/your-plugin/index.php
Kirby::plugin('custom/buttons', [
  'areas' => [
    'todos' => function () {
      return [
        'buttons' => [
          'todos.add' => function () {
            return [
              'props' => [
                'icon'   => 'add',
                'dialog' => 'todos/create'
              ]
            ];
          }
        ]
      ];
    }
  ]
]);

You have the same options for your return value: full component-props array or just props on top-level. In addition, you can also return directly a Kirby\Panel\Ui\Button\ViewButton object.

New in Alpha 3

File previews: Your media at a glance

With Kirby 5, we're opening up the preview part of the Panel's file view to more rich media previews that aren't just images.

It starts with basic previews for video and audio files that now ship as part of the core:

But you can also add custom file previews as plugin extensions to customize the preview for these formats or create previews for other file formats.

Custom file previews consist of two parts:

  • a PHP class defining what data is passed to the preview and what files this preview is used for
  • a Vue component to render the preview

Custom FieldPreview class

For a custom file preview, you need a new class that extends Kirby\Panel\Ui\FieldPreview. In this example, we're building a custom preview for .glb files that are used to display 3D data:

class GlbFilePreview extends FilePreview
{
  public function __construct(
    public File $file,
    public string $component = 'k-glb-file-preview'
  ) {
  }

  public static function accepts(File $file): bool
  {
    return $file->extension() === 'glb';
  }
}

This is the minimal setup for a custom class. What it does:

  • It defines which Vue component to use, in this case k-glb-file-preview which we will create later. If no component is specified, k-default-file-preview will be used.
  • Something you must define is the ::accepts($file) method. It is used to determine which preview class is used for a certain file. Kirby will loop through all available preview classes and use the first one that accepts the file.

Register your preview class

To use your custom file preview class, you need to register it as a plugin extension:

Kirby::plugin('your/plugin', [
  'filePreviews' => [
    GlbFilePreview::class
  ]
]);

Vue component

Finally, we need to create the Vue component that is used to render the preview. As above listed, we have named it k-glb-file-preview.

By default, file preview components will receive three default props:

  • url to the file
  • details array with basic file information (ideally used for <k-file-preview-details>)
  • image object with the thumb icon/image also used in sections etc. (we don't use it for this preview)

We also use the <k-file-preview-frame> component as wrapper for our actual 3D model, which adds a pattern background.

panel.plugin("getkirby/custom-file-preview", {
  components: {
    "k-glb-file-preview": {
      template: `
        <figure class="k-default-file-preview k-glb-file-preview">
          <k-file-preview-frame>
            <model-viewer :src="url" />
          </k-file-preview-frame>

          <k-file-preview-details :details="details" />
        </figure>
      `,
      props: {
        details: Array,
        url: String,
      },
    },
  }
});

The <model-viewer> element is from a library that helps to actually display the GLB file. I won't go into the details how to use it exactly (loading external script etc.). You can try the full custom file view.

New in Alpha 4

Versions: Preview your changes

We are finally able to release a big foundational part for one of the most requested features on our feedback platform. Editors can now make changes and get a full, rendered preview right from the Panel before they save them. They can share the URL for the preview of the unpublished changes with other editors and people in their team to get feedback.

The brand new changes view lets you switch between a comparison mode or a full-width preview of the changed version and the latest published version.

The new preview view for pages and the site is located at /panel/pages/(:any)/changes/(changes|latest|compare) and /panel/site/changes/(changes|latest|compare).

It can be accessed with the new preview dropdown for the site and pages.

… or through the page context menu …

Get more details about the changes for the current page, file or user, by accessing the new info dropdown next to the form buttons:

This dropdown will also show more information when the content is locked because another editor is currently working on it.

All changes by everyone in the team - not just the current editor - are now listed in the Changes dialog (accessible via the “Changes” menu item in the sidebar) and grouped by type (page, user, file). Now everyone in the team can directly use the dialog to jump to changes by other team members and preview them directly on the fly, even while someone else is still actively working on them.

We’ve also improved the language dropdown to highlight changes in different translations.

With all of those features built on top of our new content version architecture, Kirby 5 starts a path to full revision support in the future. We have already laid the foundations and are looking forward to extending the feature set over time.

Kirby 5 alpha 4 does not cover all special cases in regards to the handling of unsaved changes yet. For example it can not yet handle or migrate existing unsaved changes in the localStorage of individual editors' browsers that were created in Kirby 4 or Kirby 5 alphas 1 to 3. This fine-tuning will follow in future pre-releases. So we again recommend not to use Kirby 5 in production already, especially if any of the site's content currently has any unsaved changes.

New Plugin License handling

Plugin licenses are now shown in the plugins table with an additional icon and theme to indicate their status. Licenses can now have an additional link to their license document or a custom license shop. #6738

  • New Kirby\Plugin\License class
  • New Kirby\Plugin\LicenseStatus class
  • New k-table-license-cell component in the system view

Defining a plugin license as simple array

This is great if you want to point to your own license document.

App::plugin(
  name: 'my/plugin',
  extends: [...],
  license: [
    'name' => 'Custom license',
    'link' => '<https://mylicenseshop.com>',
    'status' => 'active',
  ]
);

Setting a custom status

App::plugin(
  name: 'my/plugin',
  extends: [...],
  license: [
    'name' => 'Custom license',
    'link' => 'https://mylicenseshop.com',
    'status' => [
      'value' => 'missing',
      'theme' => 'negative',
      'label' => 'Get a license please',
      'icon' => 'alert'
    ]
  ]
);

A Custom license for your plugin

You can also pass a license object. Extend our Kirby\Plugin\License class to return a custom status, them, icon and label, depending on the state of your plugin’s license. This is great if you are working with a proprietary license for your plugin, which might still need to purchased/activated by the user.

use Kirby\Plugin\License;
use Kirby\Plugin\LicenseStatus;
use Kirby\Plugin\Plugin;

class MyCustomLicense extends License
{
  public function __construct(
    protected Plugin $plugin
  ){
    $this->name = 'My Custom License';
    $this->link = '<https://mylicenseshop.com>';
    $this->status = LicenseStatus(
      value: 'missing',
      theme: 'negative',
      label: 'Get a license please',
      icon: 'alert'
    )
  }
}

App::plugin(
  name: 'my/plugin',
  extends: [...],
  license: function (Plugin $plugin) {
    return new MyCustomLicense($plugin)
  }
);

New Redis Cache Driver

Redis is one of the most used cache types. We’ve added a brand new Redis cache driver to the core. You can now use it out of the box by setting up the Redis server connection in your config. #6736

<?php

return [
    'cache' => [
        'pages' => [
            'active' => true,
            'type'   => 'redis',
            'host'   => '127.0.0.1', // default host address
            'port'   => 6379, // default port number
            'auth'   => ['user', 'password'], // optional
        ]
    ]
];

✨ Enhancements

Panel

New in Alpha 1
  • Radio and select fields: default prop supports Kirby queries #6459
  • New --color-l-min and --color-l-max CSS properties #6299
  • Relying front-end validation on native HTML invalid states #6099 #6320
    • Choice input: unselected choices get disabled when max is reached #6343
    • Added <k-input-validator> helper element to provide native form validation for complex/group inputs and fields #6321
  • <k-link> (and subsequently <k-button> and <k-dropdown-item>) has a new download attribute to force direct download of a file
New in Alpha 2
  • <k-tag>: new element and theme props #6569
  • <k-tags>: new element, element-tag and theme props #6569
  • New <k-tags-field-preview> component #6569
  • New <k-view-button> component #6540
  • New uploadAsChunks JS helper function #6421
  • New Panel\Panel::buttons() method that collects all defined buttons from all Panel areas #6541
  • New Panel\Ui namespace with basic Panel\Ui\Component and Panel\Ui\Button classes #6539
    • Each component renders as an array with a component, unique key and props entries
  • New Panel\Ui\Buttons\ViewButtons and Panel\Ui\Buttons\ViewButton classes #6542
    • responsible for gathering and transforming view buttons configured in blueprints, config files and/or Panel areas
    • renders them as PHP array definitions that can be handed to the dedicated Vue frontend components
    • Added Panel\Model::model() method
  • Backend classes for core view buttons #6545
New in Alpha 3
  • Sections: improved title and info wrapping #6447
  • Calendar input: first day of the week is chosen based on user language or date.weekday config option (0 for Sunday ... 6 for Saturday) #6635
New in Alpha 4
  • New <k-languages-dropdown> component
  • New Kirby\Panel\Ui\LanguagesDropdown class
  • New <k-form-controls> component #6512 with a new dropdown to give information about the author and last modification of the page, site, user or file.
  • New badge prop for <k-button> (value: { text, theme }) #6755
  • New this.$helper.throttle JS helper #6708
  • New options argument for this.$helper.debounce JS helper to control leading/trailing behavior #6708
  • New icons
    • asterisk
    • collapse-horizontal
    • expand-horizontal
    • layout-columns
    • layout-right
    • layout-left
    • window
  • New clipboard.write event, which can be triggered globally to write something to the clipboard. This is especially useful if you want to fire a copy event from the backend (e.g. from a dropdown option)
    this.$panel.events.emit("clipboard.write", "Add me to the clipboard");
  • <k-dropdown-content> exposes items in scoped default slot and  has new item scoped slot
  • The fields section submits all values on input of any field now (similar to on submit) instead of updating the one field #6517
  • beforeunload is now available as a global event, which you can listen to
    this.$panel.events.on("beforeunload", () => {
        // do something before the window/tab closes.
      });
  • New Kirby\Panel\Ui\PreviewDropdownButton class to show a dropdown with opening and preview options for pages and the site. (see features above)

Translations

New in Alpha 4
  • New strings
    • copy.success
    • copy.url
    • lock.unsaved.files
    • lock.unsaved.pages
    • lock.unsaved.users
    • version.changes
    • version.compare
    • view

Api

New in Alpha 4
  • New API Routes for saving, publishing and discarding of changes:
    • POST: /api/(:lock)/changes/discard
    • POST: /api/(:lock)/changes/publish
    • POST: /api/(:lock)/changes/save

Core

New in Alpha 1
  • Improved support for IDE autocompletion and type hints for collection items ($pages, $files...) #6391
  • site controller data will now always be merged as default data with data from page template specific controllers.https://feedback.getkirby.com/422
  • Thumbnails don't need to be regenerated when page sorting changes #6432
New in Alpha 2
  • New files.sort permission #1969
  • UUIDs are fully lowercased now to avoid issues between filesystems handling casing differently #6566
New in Alpha 3
  • Duplicating pages: All UUIDs within the copied page, its files and children that point to an object that got copied as - well will be replaced with the UUID of the copied version. If no copying files, any UUID pointing to a file within the copied page gets removed. #6567
New in Alpha 4
  • New ModelWithContent::version() method to directly access content versions #6455

    // Accessing different versions
    $page->version('latest');
    $page->version('changes');
    
    // Version method examples
    $page->version('changes')->content();
    $page->version('changes')->save([...]);
    $page->version('changes')->publish();
    $page->version('changes')->delete();
  • Page::previewUrl() and Site::previewUrl() now accept a version id to specify which version you want to preview.

    $page->previewUrl('latest') // default
    $page->previewUrl('changes')
  • The ModelWithContent::lock method returns the new, improved Kirby\Content\Lock class, which replaces Kirby\Cms\ContentLock

    // examples
    $page->lock()->isLocked()
    $page->lock()->modified()
    $page->lock()->modified('d.m.Y')
    $page->lock()->user()?->username()
  • New third $fail argument for Data::read() and Data::decode(). By default, Data::read() and Data::decode() will throw an exception if the file does not exist or the data cannot be decoded. By setting $fail to false, you can block the exception and return an empty array instead. We’ve refactored our parts of the code where we used a try/catch block to achieve the same.

    use Kirby\Data\Data;
    
    $data = Data::read(__DIR__ . '/missing-file.yml', fail: false);
    $data = Data::decode($brokenData, type: 'json', fail: false);
  • New $pretty argument for Json::encode()

    use Kirby\Data\Json;
    
    $prettyJson = Json::encode($data, pretty: true);
  • New Kirby\Content\Changes class replaces Kirby\Cms\ContentLocks to track all unsaved changes across all users and models. This class is mostly internal, but you can use it to get access to changed pages, files and users on the backend.

    use Kirby\Content\Changes;
    
    $changes = new Changes();
    
    // collection of changed pages
    $changes->pages();
    // collection of changed files
    $changes->files();
    // collection of changed users
    $changes->users();
  • New default changes cache, which is active by default. This cache is internally used to store all changes that have not been published yet. You can change the cache settings in your config:

    // /site/config/config.php
    return [
        'cache' => [
            'changes' => [
                'type' => 'redis'
            ]
        ]
    ];
  • New Language::ensure() and Languages::ensure() methods to get language(s) objects even in single-language mode. Note that these methods are marked as internal and may be changed in a future version. #6483

    use Kirby\Cms\Language;
    use Kirby\Cms\Languages;
    
    // for a single language
    echo Language::ensure('default')->code();
    
    // for all languages
    foreach (Languages::ensure() as $language) {
      echo $language->code();
    }

More internal enhancements

New in Alpha 4
  • New Kirby\Content\MemoryStorage for internal use #6457
  • New Kirby\Content\ImmutableMemoryStorage to keep outdated model information in memory but avoid any mutations. #6570
  • New Kirby\Content\Translation class (to eventually replace Kirby\Content\ContentTranslation)
  • New Kirby\Content\Translations class to help in ModelWithContent::translations() later and to provide a more type-safe collection for all translations.

🐛 Bug fixes

New in Alpha 1
  • Headers with null as value are no longer added to JS API requests. #6435
  • $helper.object.clone is no longer deprecated. Please use it instead of structuredClone as this might cause issues down the road with Vue 3. #6479
New in Alpha 2
  • Fixed thumb issues resulting from EXIF orientation entry #2695
  • Kirby is better at removing failed file uploads from the server tmp directory #2476
  • Canceling the file upload dialog now also cancels ongoing uploads #6421
  • <k-header>: fixed wrapping with many buttons in narrow screens #6544
New in Alpha 3
  • Model hooks for actions: multiple hooks don't overwrite each others' changes to the model #6460 #2828
New in Alpha 4
  • Fixed query support for default values in fields #2814 #2815
  • Panel search now also considers site files #6710
  • The lock state is properly passed to k-file-preview components to make sure that file previews can lock their state (e.g. for the focus point for image previews)
  • Fixed badge position in model tabs and improved CSS for button badges in general
  • Fixed background css for the k-progress component

🚨 Breaking changes

New in Alpha 1
  • Kirby requires at least PHP 8.2
  • Data/variables from your site controller will now be passed to all templates #6412
  • PHP (return) type hints have been added to many collection methods. If you are extending any collection classes, you might need to add the same to your methods.
  • CSS attribute selectors must be written fully qualified (e.g. [data-hidden="true"] as only [data-hidden] can start matching also elements where that attribute is false) #6109
  • While <k-writer> is still included as alias for <k-writer-input>, some use cases where you accessed the <k-writer> component via the $refs of <k-writer-input> have to be adapted #6172
  • Select field: empty prop was removed. Use combination of requiredplaceholder and default to replicate functionality #6459
  • <k-draggable>: the move callback function is receiving an event with an altered data structure
  • <k-form> and <k-fieldset> as well as many fields and inputs don't emit an invalid event anymore. Use native HTML invalid state of elements instead. #6099
  • novalidate prop has been removed from all elements but <k-form> #6099
  • Removed hasErorrs methods of k-fieldset #6173
  • Str::camel(), Str::camelToKebab(), Str::float(), Str::kebab(), Str::kebabToCamel(), Str::length(), Str::lower(), Str::safeTemplate(), Str::short(), Str::slug(), Str::snake(), Str::studly(), Str::substr(), Str::template(), Str::ucfirst(), Str::ucwords(), Str::unhtml(), Str::upper() and Str::widont() can no longer be called without a value argument (passing a null value still works) #6401
  • All content storage methods must now use the VersionId instead of a simple string. #6436
New in Alpha 2
  • Kirby requires the following browser versions to use the Panel (other browser requirements remain unchanged)
    • Safari 16+
    • Mobile Safari 16+
    • Android Browser 126+
    • Chrome for Android 126+
  • If file sorting was previously disabled via the files.update permission, the new file.sort permission has to be configured accordingly. #6589
  • Panel uploads can exceed the upload_max_filesize limit #6421
  • Increased PHP type hinting: when you're extending core classes, you might have to add the same type hints to your code as added to our core classes.
  • Image\Dimensions::forImage() now receives an Image\Image object #6591
  • Image\Exif::read() is now a static method that receives an absolute path to a file #6591
  • Thumb driver autoOrient option has been removed and now is always applied #6591
New in Alpha 3
  • Model action before hooks: rules get applied after the hook runs
  • <k-file-preview> got fully refactored. If you were replacing or extending it, your code likely will break. Check out the new custom file preview feature if you want to provide previews for specific files. #6578
  • Calendar dropdown input will show Sunday now as first day of the week (depending on the user's language). If you want to enforce Monday as first day of the week, you can set the date.weekday option to 1. #6635
  • All methods in *Rules classes are now marked to return void instead of a boolean #6660
  • Users without a role in their credentials file will now receive the default role (if exists), not the visitor role anymore #6656
  • Site::changes is now a new method to track changes across the site. The changes field is used as a storage for those changes and has thus become a reserved field for Kirby.
  • All methods in *Rules classes are now marked to return void instead of a boolean #6660
New in Alpha 4

Panel

  • Vuex and the Vuex content module have been removed.
  • The following dialogs no longer send dispatch evens via the backend. Dispatch events relied on Vuex.
    • page.changeTitle
    • page.delete
    • page.move
    • user.delete

Api

  • Removed API routes:
    • GET: /api/(:all)/lock
    • PATCH: /api/(:all)/lock
    • DELETE: /api/(:all)/lock
    • PATCH: /api/(:all)/unlock
    • DELETE: /api/(:all)/unlock

Translations

  • copy.success has been moved to copy.success.multiple

Core

  • signature is longer available as field property when loading fields from the Panel backend #6712
  • Kirby\Plugin\Plugin::license() now returns the License object instead of a simple string
  • Kirby\Plugin\Plugin::toArray() includes the full license info as child array instead of a string
  • ModelWithContent::version() is now a reserved keyword. If you've used a field with this name, you need to use $model->content()->get('version') instead to work with the field.
  • ModelWithContent::lock() will now always return a Kirby\Content\Lock object, even if the model is not currently locked. You can check for that case with ModelWithContent::lock()->isLocked()
  • Removed Kirby\Cms\ContentLock and Kirby\Cms\ContentLocks as well as Kirby\Cms\App::locks()
  • Page::modified(), File::modifiedContent() and User::modified() now use the current language instead of the default language.
  • panel.view.isLocked no longer exists. Use panel.content.isLocked() instead #6515
  • Kirby\Form\Field::$formFields has been renamed to Kirby\Form\Field::$siblings
  • The $formField argument in Kirby\Form\Field::factory() has been renamed to $siblings
  • You can no longer pass a value to Kirby\Form\Field::isEmpty() Use Kirby\Form\Field::isEmptyValue($value) instead.
  • Kirby\Form\Form::fields() does no longer return null but an empty Fields collection if there are no fields.
  • Kirby\Form\Field::validate() returns an array of errors instead of void. The validate method is protected and this should not really qualify as a public breaking change, but it's
    still worth noting it here.

Removed deprecated

Removed Use instead
<k-aspect-ratio> <k-frame>
<k-autocomplete> -
<k-bar>: left, right and center slots default slot
<k-breadcrumb>: view prop Add as first entry to crumbs prop
<k-button>: tooltip prop title prop
<k-button-disabled> <k-button :disabled="true">
<k-button-link> <k-button link="...">
<k-button-native> <k-button>
<k-dialog>: disabled, icon and theme props. submit-button prop
<k-dropdown> <k-dropdown-content> as standalone
<k-form-buttons> <k-form-controls>
<k-grid>: gutter prop style="gap: " or variant prop
<k-header>: left and right slots buttons slot
<k-header>: tabs prop standalone <k-tabs>
<k-headline>: size prop tag prop
<k-headline>: theme prop -
<k-icon>: removed support for other viewBox than 0 0 24 24 Wrap icon in an <svg> element with corresponding viewBox attribute
<k-inside> <k-panel-inside>
<k-loader> <k-icon type="loader" />
<k-outside> <k-panel-outside>
<k-plugin-view> -
<k-progress>: set method value prop
<k-text>: theme prop -
<k-upload> this.$panel.upload module
<k-view> -
this.$panel.dialog.successDispatch() -
this.$panel.drawer.successDispatch() -
this.$store -
this.$store.drawer this.$panel.drawer
this.$store.notification this.$panel.notification
this.$store.dialog() this.$panel.dialog.open()
this.$store.drag() this.$panel.drag.start(type, data)
this.$store.fatal() this.$panel.notification.fatal()
this.$store.isLoading() this.$panel.isLoading
this.$store.navigate() -
this.$events.$on this.$panel.events.on
this.$events.$off this.$panel.events.off
this.$events.$emit this.$panel.events.emit
Array.wrap() this.$helper.array.wrap()
Array.fromObject() this.$helper.array.fromObject()
myArray.split() this.$helper.array.split(myArray, delimiter)
myArray.sortBy() this.$helper.array.sortBy(myArray, sortBy)
Kirby\Cms\App::locks() -
Kirby\Cms\ContentLock Kirby\Content\Lock
Kirby\Cms\ContentLocks Kirby\Content\Changes
Kirby\Cms\File::contentFileDirectory() -
Kirby\Cms\File::contentFileName() -
Kirby\Cms\Model -
Kirby\Cms\ModelWithContent::contentFile() $model->storage()->contentFile()
Kirby\Cms\ModelWithContent::contentFiles() $model->storage()->contentFiles()
Kirby\Cms\ModelWithContent::contentFileDirectory() -
Kirby\Cms\ModelWithContent::contentFileName() -
Kirby\Cms\ModelWithContent::contentFileExtension() -
Kirby\Cms\Page::contentFileName() -
Kirby\Cms\Properties trait PHP native named properties
Kirby\Cms\Site::contentFileName() -
Kirby\Cms\User::contentFileName() -
Kirby\Form\FieldClass::valueFromJson() Kirby\Data\Json::decode()
Kirby\Form\FieldClass::valueFromYaml() Kirby\Data\Yaml::decode()
Kirby\Form\FieldClass::valueToJson() Kirby\Data\Json::encode()
Kirby\Form\FieldClass::valueToYaml() Kirby\Data\Yaml::encode()

☠️ Deprecated

New in Alpha 1
  • <k-writer> will be removed in a future version. Use <k-writer-input> instead #6172
  • --color-backdrop CSS property has been deprecated. Use --overlay-color-back instead #6299
New in Alpha 2
  • <k-bubble>, <k-bubbles> and <k-bubbles-field-preview>. Use <k-tag>, <k-tags> and <k-tag-field-preview> instead. #6569
New in Alpha 3
  • Exception classes: passing $arg array will be removed in a future version. Use named arguments. #6618
New in Alpha 4

♻️ Refactored

New in Alpha 1
  • <k-writer> has been merged into <k-writer-input> #6172
  • Streamline input validation
    • Use <k-string-input> for all text inputs #6103
    • <k-slug-input> is now built on top of <k-string-input> #6320
    • Stricter native URL validation for <k-url-input> #6320
    • Removed vuelidate library #6099
  • Preparations for a move to Vue 3 in v6
    • <k-draggable> is directly built on top of SortableJS now #6387
    • Replace Vue $listeners #6107
    • Use strict CSS selectors for boolean (data) attributes #6109
    • Explicitly added $attrs.class to components that disable inheriting attributes #6332
    • Use more modern PHP syntax and PHPUnit assertions where applicable #6401
  • Improved class typing by adding Stringable interface to relevant classes #6433
  • New Kirby\Content\VersionId class to represent versions #6436
  • Refactored all content storage classes and models to use the new VersionId #6436
  • Refactor PlainTextStorageHandler implementation #6439
  • Remove option to pass null as language to internal ContentStorageHandler::exists method to avoid unwanted logic in handler methods. #6439
  • New Version class which inherits the logic from the ContentStorage handler and replaces it.
  • New Language::single() method to create a Language placeholder object in single language installations #6448
  • Use full language objects in ContentStorageHandler and PlainTextContentStorageHandler methods #6448
  • Convert the ContentStorageHandler interface to an abstract class #6449
  • Use "new" functions from PHP 8.0 #6476
    • str_contains()
    • str_starts_with()
    • str_ends_with()
New in Alpha 2
  • New Kirby\Api\Upload class to handle file uploads via the REST API #6421
New in Alpha 3
New in Alpha 4

Panel

  • <k-languages-dropdown> now receives Fiber dropdown endpoint instead of array of options #6762
  • New Kirby\Panel\Controller\Search class #6710
  • Removed unnecessary generic signature key for each form field. #6712
  • New this.$panel.content module to access and alter the current model content (unsaved changes) #6513
  • <k-user-avatar> component has been refactored to use individual props for api, avatar, id and isLocked instead of going through the model object. The model prop has been removed.
  • The <k-user-profile> component has been refactored to use individual props for api, avatar, email, id, language and role instead of going through the model object. The model object prop has been removed as well as the already deprecated permissions prop.
  • Drastically simplified Kirby\Panel\ChangesDialog class, which reads changed models directly on the backend with the new Kirby\Content\Changes class and sends the required data for each model directly to the frontend. We no longer need an additional async request.
  • Refactored Kirby\Panel\Model classes
    • Removed Kirby\Panel\Model::lock() method
    • New Kirby\Panel\Model::originals() method
    • New top-level props in Kirby\Panel\Model::props()
      • api
      • id
      • link
      • originals
      • uuid
    • New top-level props in Kirby\Panel\File::props()
      • extension
      • filename
      • mime
      • preview
      • type
      • url
    • New top-level props in Kirby\Panel\Page::props()
      • title
    • New top-level props in Kirby\Panel\Site::props()
      • title
    • New top-level props in Kirby\Panel\User::props()
      • avatar
      • email
      • language
      • name
      • role
      • username

Model refactoring

  • Use ModelWithContent::version() in the core where it makes sense #6455
  • Page::__construct calls parent::__construct after setting the props #6499
  • Site::__construct calls parent::__construct after setting the props #6499
  • User::__construct calls parent::__construct after setting the props #6499
  • File::__construct calls parent::__construct after setting the props #6499
  • Simplify ModelWithContent::writeContent by using the new Version::save() method. #6505
  • Simplify ModelWithContent::content by using Language::ensure() and Version::content() #6505

Form class refactoring

  • Kirby\Form\Field class improvements

    • New Field::fill($value) method
    • New Field::toFormValue() method
    • New Field::toStoredValue() method
  • Kirby\Form\FieldClass class improvements

    • New FieldClass::fill($value) method
    • New FieldClass::toFormValue() method
    • New FieldClass::toStoredValue() method
  • Kirby\Form\Fields class improvements

    • You can now pass the parent model as second argument to the Fields collection to inject it into any of the given fields.

      use Kirby\Form\Fields;
      
        $fields = new Fields(
            fields: [
              'text' => [
                'label' => 'Text',
                'type'  => 'text'
                ]
            ],
            model: page('blog/hello-world')
        );
    • New Fields::defaults() method to return all default values for all fields.

    • New Fields::errors() method to run validation on all fields and return an array with all errors

    • New Fields::fill($values) method to set the value for each field in the array

    • New Fields::findByKey() and Fields::findByKeyRecursive() to find fields within fields with Fields::find('parent-field+child-field') (e.g. a field in a structure field) This has been handled by the Form::field() method before, but it's the wrong place to do that. With the new collection methods, this is handled in a very similar fashion as we do for pages.

    • Improved Fields::toArray() method. You can now provide a proper map function to return custom values for each field in the collection.

    • New Fields::toFormValues() to return all values for all fields in the collection that can be passed to a frontend form.

    • New Fields::toStoredValues() to return all values for all fields in a format that can be stored in our text files.

  • Kirby\Form\Form class improvements

    • The Form class now always passes the injected model to the Fields collection
    • The Form class now uses Field::isSaveable instead of Field::save consistently.
    • Form::errors() is now an alias for $form->fields()->errors()
    • Form::field($name) is now an alias for $form->fields()->find($name)
    • New Form::toFormValues() to return all values for all fields in the collection that can be passed to a frontend form.
    • New Form::toStoredValues() to return all values for all fields in a format that can be stored in our text files.
    • Removed an unnecessary check for a blueprint method in the Form::for method. ModelWithContent has a blueprint method by default and we
      already check for ModelWithContent child classes with the argument type.
  • New Form Field Trait classes to help reduced code redundancy between Kirby\Form\Field and Kirby\Form\FieldClass

    • Kirby\Form\Mixin\Api
    • Kirby\Form\Mixin\Model
    • Kirby\Form\Mixin\Translatable
    • Kirby\Form\Mixin\Validation
    • Kirby\Form\Mixin\Value
    • Kirby\Form\Mixin\When

Additional core refactoring

  • New Kirby\Plugin namespace #6737
  • New Kirby\Toolkit\Component::applyProp() method to allow resetting single props and also improves prop unsetting in custom components.

🧹 Housekeeping

New in Alpha 1
  • Extended rule list for php-cs-fixer #6398
  • Tests: DRY $app property #6474
  • Replacing get_class() method with ::class notation #6475
New in Alpha 2
  • Vite: Make dev server by default https://sandbox.test instead of http://sandbox.test #6522
  • Turn panel JS modules fully reactive #6529
  • The ::setUpSingleLanguage and ::setUpMultiLanguage helper test methods in global TestCase class. #6561
New in Alpha 4
  • All changes from the upcoming 4.5.0 release are also in alpha 4.