Releases: getkirby/kirby
5.2.1
6.0.0-alpha.1 – Developer Preview
TL;DR:
Kirby 6.0.0-alpha.1 is a very early developer preview with Vue 3 support, backend refactoring but no new features at this point. If you are not working on third-party plugins or your own custom Panel extensions, you can happily skip this release for now. Pre-releases with features and enhancements will follow in early 2026.
Important
Don't use Kirby 6 in production yet
ETA for Kirby 6
We plan for a final release in the second half of 2026.
What about Kirby 5?
Kirby 5 is our latest and greatest release and will be relevant for many more months. We will be releasing new updates and features and there’s absolutely no reason to already think about Kirby 6 at this point if you are not a plugin developer.
Upgrade prices?
According to our license model that we started with Kirby 4, Kirby 6 will be a free upgrade for anyone who bought or will buy a Kirby Basic or Kirby Enterprise license, no matter if you were one of the first with Kirby 4 or if your project just started. You can recognize this if your license key starts with K-BAS or K-ENT. You can buy a Kirby license today and upgrade for free to Kirby 6 at any point later in 2026.
We are migrating to Vue 3
What are the benefits for you?
- Security
- A future-proof ecosystem
- Better Panel performance (Vue 3 is faster and smaller than Vue 2)
Details
Vue 2 has reached its End of Life in December 2024, which means that it does no longer get security updates. There are so far no vulnerabilities that affect you directly. But this could change any time. To keep Kirby secure in the future, we have to take this step and upgrade to Vue 3. The End Of Life for Vue 2 also means that the Vue ecosystem has shifted to Vue 3 support and it’s getting harder and harder to get good third party libraries and components that still support Vue 2. This is not a good state for the future of Kirby’s ecosystem.
Why not earlier?
With the upgrade to Vue 3, all third-party plugins for the Panel also need to be upgraded to Vue 3. This is a huge step and we have to prepare it carefully, to provide a good path for Kirby’s ecosystem. We also had our own challenges to migrate to Vue 3 without breaking too much of our own components and APIs. But we feel ready now to take this step to create a solid foundation.
There is no need to worry about security for sites with Kirby 4 and Kirby 5. You can omit the vulnerable parts of Vue 2 by disabling the Vue template compiler.
How can you test Kirby 6.0.0-alpha.1?
The easiest way is to install a fresh starterkit and replace the kirby folder with the one from this release (see ZIP download below) The starterkit should already be fully compatible. The alpha label should make it clear enough, but here's a word of warning again. Don't use this release in production and always make backups of your projects and especially the content. We don't take any responsibility for issues that lead to content-loss or other nasty side-effects.
What do you need to do next?
As plugin developer
If you are maintaining Kirby plugins that extend the Panel, you need to upgrade them with the latest alpha version of kirbyup. You will have plenty of time to prepare this until the final release of Kirby 6. But the earlier you discover potential problems, the sooner we can work together on fixing them.
Here are the steps to take to migrate your plugin to Vue 3:
- Switch your kirbyup version in your package.json to 4.0.0-alpha.3
- Run
npm run build - Test your plugin in the Panel, check for Vue 3 warnings in the console
- Adapt your plugin code if you encounter any warning
- Reach out to the Kirby team in the #v6 channel on Discord if you encounter any problems or difficulties upgrading
As site developer
If you are writing custom Panel plugins for your clients, you can already try to upgrade one of your plugins and see if you get it up and running with alpha 1. Follow the instructions for plugin developers above in such a case. Otherwise, this first alpha will probably not be very exciting for you yet and you might want to wait some more until we have more features to show or the first plugins are ready to be tested.
As customer
Nothing at this point. This really is a developer preview. We will have more exciting Kirby 5 and 6 updates for you in the following months.
Work in progress
- We've started refactoring our backend code for the Panel, to be easier to extend, test and optimize.
- Our entirel Panel backend setup is closer to what we are also doing on the frontend.
- We have a new Controller architecture for all views, dialogs, drawers and requests.
- We have a new Kirby\Panel\Ui backend library of digital-twins for our frontend components. This library makes it easier for plugin developers and us, to create type-safe responses for our Vue frontend.
- We are working on refactoring our core fields to be PHP class based. These are already taking the Panel performance to an entirely new level in our tests. More in alpha.2.
- We are making our blueprints simpler. More details will follow soon.
- After this foundational work, we have plenty of ideas and plans for features, based on your feedback on Nolt.
Full changelog
We are collecting all changes in our pre-release changelog, if you already want to dive deeper: https://github.com/getkirby/kirby/blob/6.0.0-alpha.1/CHANGELOG.md
5.2.0
🤩 Highlights
- 🐘 PHP 8.5 support
- 📻 CORS support
- ☑️ New
batchselect mode for the checkboxes field ↕️ Collapse / expand all blocks- 📂 New
createoption for the files section - 🏷️ Better auto-labels in the Panel
- ⚡️ Big performance boost for forms
🎉 Features
PHP 8.5 support
PHP 8.5 has been released a few days ago and it's a fantastic release (https://www.php.net/releases/8.5/en.php) Kirby 5.2 is already fully compatible. #7671
Automatic handling of CORS (Cross-Origin Resource Sharing)
For headless setups, proper CORS support is incredibly helpful to speak to your Kirby API, content representations or KQL across domains. Thanks to the help of @johannschopplich, Kirby is now making this very easy out of the box.
How It Works
- Simple setup: Set
'cors' => trueto enable CORS with sensible defaults. Check below for additional configuration options. - Automatic preflight handling: When CORS is enabled, all
OPTIONSCORS preflight requests automatically receive a204 No Contentresponse with appropriate CORS headers. - Header injection: CORS headers are lazily injected into the
Responder::headers()method for all responses. Custom headers set by plugins or user code are never overridden. - Vary header management (Hono inspired):
- Wildcard origins (
*): NoVary: Originheader is added (cache-efficient since response is identical for all origins) - Specific origins: Automatic
Vary: Originheader ensures different origins are cached separately - Header reflection: Automatic
Vary: Access-Control-Request-Headersfor preflight requests when reflection is enabled - Auth/Cookie tracking: Automatic
Vary: Authorization, Cookiewhen response uses authentication or cookies - Smart merging: All Vary values are combined intelligently without duplication
- Wildcard origins (
- Header reflection opt-in: With
'allowHeaders' => true, preflight requests mirror the headers requested by the client whileVary: Access-Control-Request-Headersensures correct caching. The default[]remains secure-by-default by omitting the header.
Configuration
CORS can be enabled in three ways:
1. Boolean (uses all defaults)
return [
'cors' => true
];2. Array (custom configuration)
return [
'cors' => [
'allowOrigin' => 'https://example.com',
'allowCredentials' => true
]
];3. Closure (dynamic/request-based)
return [
'cors' => function ($kirby) {
$origin = $kirby->request()->header('Origin');
// Allow specific origins with credentials
if (in_array($origin, ['https://app1.com', 'https://app2.com'])) {
return [
'allowOrigin' => $origin,
'allowCredentials' => true,
'allowMethods' => ['GET', 'POST']
];
}
// Fallback to wildcard for other origins
return ['allowOrigin' => '*'];
}
];Note: Setting 'cors' => [] (empty array) is equivalent to 'cors' => true and enables CORS with defaults. To disable CORS, use 'cors' => false or omit the option entirely.
Available Options
| Option | Type | Default | Description |
|---|---|---|---|
allowOrigin |
string, array |
'*' |
Allowed origins (e.g., '*', 'https://example.com', or ['https://app1.com', 'https://app2.com'] for multiple origins) |
allowMethods |
string, array |
['GET', 'HEAD', 'PUT', 'POST', 'DELETE', 'PATCH'] |
Allowed HTTP methods for preflight requests |
allowHeaders |
string, array, bool |
[] |
Allowed request headers. [] (default) suppresses Access-Control-Allow-Headers; true reflects headers from Access-Control-Request-Headers; strings/arrays allowlist specific headers explicitly |
maxAge |
int |
null |
Preflight cache duration in seconds. null uses the browser default (typically 5 seconds) |
allowCredentials |
bool |
false |
Allow requests with credentials (cookies, auth). Cannot be true with wildcard origin |
exposeHeaders |
string, array |
[] |
Response headers exposed to the browser |
Security considerations:
- Enabling CORS allows external origins to interact with your Kirby site. This means that sites hosted on external origins (domains) can access or control your Kirby site via the browser of their visitors. Only enable CORS when needed, and restrict the configuration (origins, methods, headers) to the minimum required for your use case.
'allowCredentials' => truelets browsers include cookies and HTTP authentication with cross-origin requests, effectively granting the external origin the same permissions as the logged-in user. Only enable credentials when the requesting origin is fully trusted and under your control.
New batch select mode for the checkboxes field
You can now switch on the select all/deselect all toggles with the new batch option in the checkboxes field to select or deselect multiple checkboxes at once. This is helpful when a checkboxes field has a lot of options https://feedback.getkirby.com/81 #7659
fields:
countries:
type: checkboxes
options:
# lots of countries
batch: truecheckboxes.mp4
Thanks to this new feature, we now also have the following additions:
- New
select-allanddeselect-allicons - New
select.all,deselect.allanddeselecttranslation strings
Collapse / expand all blocks
There are new options to expand or collapse all blocks at once in the blocks options dropdown (if there are collapsible blocks used, e.g. with preview: fields) (thx @dennisbaum) #7555
New create option for the files section
The new create option for the files section lets you disable the upload button. This is useful if you are using queries in files sections and the upload would not actually show up in the list. It is comparable to the create option in the pages section. #7649
sections:
images:
type: files
query: page.images.filter('customField', 'customFilter')
create: falseBetter auto-labels in the Panel
We've improved our auto-labelling method for labels, titles and more in various places of the Panel. Here's an example from a blueprint #7656:
sections:
coverImages:
type: filesThe files section above does not define a label, but already has a meaningful name, which can now be turned into one. In previous releases coverImages would have been turned into the auto-label Coverimages. Not that nice. Now camel casing automatically turns it into Cover images. This also works if you prefer kebab-casing.
sections:
cover_images:
type: filesThis will very often save you from defining additional label/title/name options. This can now help you in the following places:
- Blueprint title
- Blueprint tab labels
- Section headlines
- Form field labels
- Block field: fieldset names
- Block field: fieldset tab names
- Block field: fieldset group names
- Role titles
- Custom panel search labels
This feature is based on our new Kirby\Toolkit\Str::label() method, which you can of course use in your own code, to create nice auto-labels.
⚡️ Performance
We've managed to achieve massive performance improvements for forms. In our test setup we measure two different scenarios:
1. Generating the backend props for all fields and their custom configurations.
5.1.4: 00:06.198
5.2.0: 00:03.045
≈ 50.9% reduction in time
≈ 2.04× speed-up
2. Generating the backend props for all our field related panel views.
5.1.4: 00:19.390
5.2.0: 00:05.900
≈ 69.6% reduction in time
≈ 3.29× speed-up
Our test sandbox is of course a very theoretical environment, but we still expect to see some serious improvements in real-world setups.
The following steps lead to this improvement:
- New ::emptyValue() method for Kirby\Form\Field and Kirby\Form\FieldClass, which can be overwritten to define the preferred empty value when the field is being reset #7663
- New Kirby\Form\Field::fillWithEmptyValue() and Kirby\Form\FieldClass:reset(), which are used in Kirby\Form\Fields to reset field values without evaluating computed props again if not
necessary. This is the part that leads to the performance improvements. #7663
- Field options are now cached in memory to improve the performance of fields. #7664
- New protected BlocksField::fieldsetForm method to cache forms for each fieldset type. #7665
- Fixes: #7641 and #6734
We've also added a new in-memory snippet cache to speed up snippet lookups and avoid disk access #7369
✨ Enhancements
- Plugin links point to
plugins.getkirby.comdirectory if plugin is listed there #7243 - View button: `opti...
5.2.0-rc.1
🤩 Highlights
- 🐘 PHP 8.5 support
- 📻 CORS support
- ☑️ New
batchselect mode for the checkboxes field ↕️ Collapse / expand all blocks- 📂 New
createoption for the files section - 🏷️ Better auto-labels in the Panel
- ⚡️ Big performance boost for forms
🎉 Features
PHP 8.5 support
PHP 8.5 has been released a few days ago and it's a fantastic release (https://www.php.net/releases/8.5/en.php) Kirby 5.2 is already fully compatible. #7671
Automatic handling of CORS (Cross-Origin Resource Sharing)
For headless setups, proper CORS support is incredibly helpful to speak to your Kirby API, content representations or KQL across domains. Thanks to the help of @johannschopplich, Kirby is now making this very easy out of the box.
How It Works
- Simple setup: Set
'cors' => trueto enable CORS with sensible defaults. Check below for additional configuration options. - Automatic preflight handling: When CORS is enabled, all
OPTIONSCORS preflight requests automatically receive a204 No Contentresponse with appropriate CORS headers. - Header injection: CORS headers are lazily injected into the
Responder::headers()method for all responses. Custom headers set by plugins or user code are never overridden. - Vary header management (Hono inspired):
- Wildcard origins (
*): NoVary: Originheader is added (cache-efficient since response is identical for all origins) - Specific origins: Automatic
Vary: Originheader ensures different origins are cached separately - Header reflection: Automatic
Vary: Access-Control-Request-Headersfor preflight requests when reflection is enabled - Auth/Cookie tracking: Automatic
Vary: Authorization, Cookiewhen response uses authentication or cookies - Smart merging: All Vary values are combined intelligently without duplication
- Wildcard origins (
- Header reflection opt-in: With
'allowHeaders' => true, preflight requests mirror the headers requested by the client whileVary: Access-Control-Request-Headersensures correct caching. The default[]remains secure-by-default by omitting the header.
Configuration
CORS can be enabled in three ways:
1. Boolean (uses all defaults)
return [
'cors' => true
];2. Array (custom configuration)
return [
'cors' => [
'allowOrigin' => 'https://example.com',
'allowCredentials' => true
]
];3. Closure (dynamic/request-based)
return [
'cors' => function ($kirby) {
$origin = $kirby->request()->header('Origin');
// Allow specific origins with credentials
if (in_array($origin, ['https://app1.com', 'https://app2.com'])) {
return [
'allowOrigin' => $origin,
'allowCredentials' => true,
'allowMethods' => ['GET', 'POST']
];
}
// Fallback to wildcard for other origins
return ['allowOrigin' => '*'];
}
];Note: Setting 'cors' => [] (empty array) is equivalent to 'cors' => true and enables CORS with defaults. To disable CORS, use 'cors' => false or omit the option entirely.
Available Options
| Option | Type | Default | Description |
|---|---|---|---|
allowOrigin |
string, array |
'*' |
Allowed origins (e.g., '*', 'https://example.com', or ['https://app1.com', 'https://app2.com'] for multiple origins) |
allowMethods |
string, array |
['GET', 'HEAD', 'PUT', 'POST', 'DELETE', 'PATCH'] |
Allowed HTTP methods for preflight requests |
allowHeaders |
string, array, bool |
[] |
Allowed request headers. [] (default) suppresses Access-Control-Allow-Headers; true reflects headers from Access-Control-Request-Headers; strings/arrays allowlist specific headers explicitly |
maxAge |
int |
null |
Preflight cache duration in seconds. null uses the browser default (typically 5 seconds) |
allowCredentials |
bool |
false |
Allow requests with credentials (cookies, auth). Cannot be true with wildcard origin |
exposeHeaders |
string, array |
[] |
Response headers exposed to the browser |
Security considerations:
- Enabling CORS allows external origins to interact with your Kirby site. This means that sites hosted on external origins (domains) can access or control your Kirby site via the browser of their visitors. Only enable CORS when needed, and restrict the configuration (origins, methods, headers) to the minimum required for your use case.
'allowCredentials' => truelets browsers include cookies and HTTP authentication with cross-origin requests, effectively granting the external origin the same permissions as the logged-in user. Only enable credentials when the requesting origin is fully trusted and under your control.
New batch select mode for the checkboxes field
You can now switch on the select all/deselect all toggles with the new batch option in the checkboxes field to select or deselect multiple checkboxes at once. This is helpful when a checkboxes field has a lot of options https://feedback.getkirby.com/81 #7659
fields:
countries:
type: checkboxes
options:
# lots of countries
batch: truecheckboxes.mp4
Thanks to this new feature, we now also have the following additions:
- New
select-allanddeselect-allicons - New
select.all,deselect.allanddeselecttranslation strings
Collapse / expand all blocks
There are new options to expand or collapse all blocks at once in the blocks options dropdown (if there are collapsible blocks used, e.g. with preview: fields) (thx @dennisbaum) #7555
New create option for the files section
The new create option for the files section lets you disable the upload button. This is useful if you are using queries in files sections and the upload would not actually show up in the list. It is comparable to the create option in the pages section. #7649
sections:
images:
type: files
query: page.images.filter('customField', 'customFilter')
create: falseBetter auto-labels in the Panel
We've improved our auto-labelling method for labels, titles and more in various places of the Panel. Here's an example from a blueprint #7656:
sections:
coverImages:
type: filesThe files section above does not define a label, but already has a meaningful name, which can now be turned into one. In previous releases coverImages would have been turned into the auto-label Coverimages. Not that nice. Now camel casing automatically turns it into Cover images. This also works if you prefer kebab-casing.
sections:
cover_images:
type: filesThis will very often save you from defining additional label/title/name options. This can now help you in the following places:
- Blueprint title
- Blueprint tab labels
- Section headlines
- Form field labels
- Block field: fieldset names
- Block field: fieldset tab names
- Block field: fieldset group names
- Role titles
- Custom panel search labels
This feature is based on our new Kirby\Toolkit\Str::label() method, which you can of course use in your own code, to create nice auto-labels.
⚡️ Performance
We've managed to achieve massive performance improvements for forms. In our test setup we measure two different scenarios:
1. Generating the backend props for all fields and their custom configurations.
5.1.4: 00:06.198
5.2.0: 00:03.045
≈ 50.9% reduction in time
≈ 2.04× speed-up
2. Generating the backend props for all our field related panel views.
5.1.4: 00:19.390
5.2.0: 00:05.900
≈ 69.6% reduction in time
≈ 3.29× speed-up
Our test sandbox is of course a very theoretical environment, but we still expect to see some serious improvements in real-world setups.
The following steps lead to this improvement:
- New ::emptyValue() method for Kirby\Form\Field and Kirby\Form\FieldClass, which can be overwritten to define the preferred empty value when the field is being reset #7663
- New Kirby\Form\Field::fillWithEmptyValue() and Kirby\Form\FieldClass:reset(), which are used in Kirby\Form\Fields to reset field values without evaluating computed props again if not
necessary. This is the part that leads to the performance improvements. #7663
- Field options are now cached in memory to improve the performance of fields. #7664
- New protected BlocksField::fieldsetForm method to cache forms for each fieldset type. #7665
- Fixes: #7641 and #6734
We've also added a new in-memory snippet cache to speed up snippet lookups and avoid disk access #7369
✨ Enhancements
- Plugin links point to
plugins.getkirby.comdirectory if plugin is listed there #7243 - View button: `opti...
5.1.4
🚨 Security
Cross-site scripting (XSS) in the changes dialog
Severity: medium (CVSS score 5.1)
This vulnerability affects all Kirby 5 sites that might have potential attackers in the group of authenticated Panel users or that allow external visitors to update page titles or usernames.
The attack requires user interaction by another Panel user and cannot be automated.
✨ Enhancements
- Improve the wording and layout of the "Change Password" dialog #7621
🐛 Bug fixes
- Fixed type hints of
css()andjs()helpers #7645 - Pages field dialog lists unwanted pages after navigating back from subpages #7624
- The large margin below the user profile in the user view is now gone and tabs are set directly below #7651
- Don’t hide the required asterisk in the field label if the input prop is false. #7642
♻️ Refactored
- Use the new UI Item classes to create the props for model's dropdown options. #7650
🧹 Housekeeping
- Updated PHP and JS dependencies
5.1.3
✨ Enhancements
- Allow specifying the page model class of a
Kirby\Cms\Pagescollection via PHP DocBlock type tags #7617
🐛 Bug fixes
- Converted blocks from old builder field do not store anymore system data as additional content (thx @mrflix) #7616
- Range field: Fixed tooltip width for negative/decimal values #7614
- Deleting sorted pages recursively or in a batch could lead to unwanted side effects and left-over folders and files. This fix will now make sure that all pages are properly deleted. #7623 & #7615
- Shows placeholder in Panel view when site title is missing #7628
- Fix placeholder color in dark mode in the user view header.
- The position select field is now required (as it should be) #7633
- The model fields no longer accidentally pass a click on the label to the remove button #7631
🧹 Housekeeping
5.1.2
✨ Enhancements
- Page status button in sections received a
.k-page-status-icon-optionCSS class #7592
🐛 Bug fixes
- Added back
usersas entry point for Kirby queries #7597 - Fixed language detection when browser provides partial locale/code that could refer to multiple supported languages. Kirby now will prefer the language where the language code is an exact match. #7604
$panel.content.isLockedreturnsfalsewhen view does not provide alockprop #7602- Reloading a dialog/drawer will no longer nest the new dialog/drawer but replace the previous one #7609
5.1.1
5.1.0
🎉 Features
Navigation for the preview view
We've added a handy page tree navigation dropdown to the preview view. Effortlessly jump to the preview of other pages #7335
Query language
Kirby 5.1 adds a number of improvements to the Kirby Query language. Since the query language plays such an essential part for Kirby's blueprints, the new query improvements will push the possibilities for blueprints even further.
The improvements are based on a new AST-based query parser and runner that has been added in addition to the previous (legacy) parser. The legacy parser will remain the default parser for now. We aim to replace it with the new runner in Kirby 6. Consider the new runner as a beta state during Kirby 5.x releases. #6788
The new AST-based runner (thanks to @rasteiner for starting off the work on this) runs not only more reliably and performant, but also allow us to add more functionalities. Those are not supported by the legacy runner.
- Support for more operators:
- Logic (
AND/&&/OR/||) - Compare (
==,!=,>,<,<=,>=) - Math (
+,-,*,/,%)
- Logic (
- Closures in queries can now accept arguments
- Queries support subscript access notation, e.g.
page[site.pageMethodName] - New
query.runneroption to switch to theKirby\Query\Runners\DefaultRunner::classto activate the new AST-based runner (see docs below for more information how to create a custom runner)
The new query runner is stricter in parsing queries. In some edge cases, this will require you to access an array/object via subscript notation - in rare cases on the top level via the new this keyword, e.g. this["identifier.with dots and spaces"].
Batch delete for structures
New batch mode for structure fields to delete multiple rows at once. You can activate it by using the new batch option in your blueprint (#7400):
structure:
batch: true
fields:
text:
type: text
structures.mov
Searchable info in multiselect fields
You can now search through the info in a multiselect field by enabling the search > info option. (Thanks to @aofn) #7089
fields:
multiselect:
type: multiselect
options:
...
search:
info: true
Stats field
We’ve turned the stats section into an additional new field. The stats section keeps existing, but with the new stats field there are more layout possibilities and options for simpler blueprint setups. The field has the exact same options as the stats section (https://getkirby.com/docs/reference/panel/sections/stats). #7392
title: Shop
fields:
stats:
type: stats
size: huge
reports:
- label: Revenue
value: €29,682
info: +112.5%
link: https://getkirby.com/shop
theme: positive
- label: Orders
value: 265
info: +82.8%
theme: positive
- label: Avg. Transaction
value: €112.01
info: +16.3%
theme: positive
- label: Refunds
value: €15.20
info: +10.5%
theme: positive
- label: Discount sales
value: €1,422
info: n/aImagick thumb driver
New imagick thumbs driver, using the Imagick class instead of the convert command line command #6754
// /site/config/config.php
return [
'thumbs' => [
'driver' => 'imagick'
]
];Set the default panel.theme
You can now set the default Panel theme that is used when the user has not set any custom setting in their account view. Supported values: "light", "dark" or "system" (default, matches the user's operating system) #7341
// site/config/config.php
return [
'panel' => [
'theme' => 'light'
]
];New Collection::join() method
This new method is available in all collections #7340 (thx to @adamkiss)
$venues = $page->children()->join(' | ', fn ($child) => $child->venue());
$venues = $page->children()->join(as: fn ($child) => snippet('venue', ['page' => $child], return: true));New session.cookieDomain option
The option allows to share the session cookie across subdomains with a shared sessions folder feedback.getkirby.com/628
Note
You can read more about the behavior of the domain attribute for cookies in the MDN docs.
Note that setting the cookieDomain option disables Kirby setting the path attribute to the cookie (relevant in subfolder setups).
return [
'session' => [
'durationNormal' => 7200, // default: 2 hours
'durationLong' => 1209600, // default: 2 weeks
'timeout' => 1800, // default: half an hour
'cookieDomain' => 'getkirby.com', // default: automatic browser behavior
'cookieName' => 'kirby_session',
'gcInterval' => 100 // default: cleanup every ~100 requests
]
];Dialog search input improvements
The dialog search input has a new button to clear the input #7513
search.mov
Option to delete a license
The license dialog now includes a button to remove the license file #6962 #6960
✨ Enhancements
Support for nested dialogs
We've added history support for panel.dialog for nested dialogs #7519 Dialogs can now correctly open more dialogs which will be stacked on top of each other and close correctly.
Improved UI for the structure field
We've improved the UI when the structure field is disabled that allows to open drawer to see all fields as well as navigate through all entries when paginated https://feedback.getkirby.com/687
Improved language detector
Our language detector will now correctly detect languages based on locales. You can now easily set up two English locales (en_GB and en_US) for example and the detector will pick the right one and redirect correctly. (thanks to @tobiasfabian) #7178
Change the panel translation via URL
You can now set the Panel interface translation on demand with the new translation query parameter. E.g. https://example.com/panel/login?translation=it #6616
Better fatal view
We've added a link to the PHP version support table from the fatal view that is displayed on unsupported PHP versions
New skeleton theme for items
We've added a new sekeleton theme for the k-item component to represent a loading state #7521
Snippet controllers
With Kirby 5.1 you can create a small plugin that enables support for snippets and block controllers: one can add a controller for e.g. the snippet site/snippets/header.php to site/controllers/snippets/header.php. And since blocks are also just snippets, e.g. site/controllers/snippets/blocks/video.php.
As there can be many snippet calls within a single request, checking for the existence of a controller for each of these can impact your site’s performance.
<?php
use Kirby\Cms\App;
use Kirby\Template\Snippet;
use Kirby\Toolkit\Str;
class SnippetWithController extends Snippet
{
protected static $controllers = [];
public static function controller(
string|null $file,
array $data = []
): array {
if (
$file === null ||
str_starts_with($file, static::root()) === false
) {
return $data;
}
if (isset(static::$controllers[$file])) {
return array_replace_recursive(
$data,
static::$controllers[$file]
);
}
$name = ltrim(Str::before(Str::after($file, static::root()), '.php'), '/');
// if the snippet has a name, we can load the controller
// and merge the data with the controller's data
if ($name !== null) {
$data = array_replace_recursive(
$data,
static::$controllers[$file] = App::instance()->controller('snippets/' . $name, $data)
);
}
return $data;
}
public static function factory(
string|array|null $name,
array $data = [],
bool $slots = false
): static|string {
$file = $name !== null ? static::file($name) : null;
$data = static::controller($file, $data);
return parent::factory($name, $data, $slots);...5.1.0-rc.1
🎉 Features
Navigation for the preview view
We've added a handy page tree navigation dropdown to the preview view. Jump effortlessly to the preview of other pages #7335
Query language
Kirby 5.1 adds a number of improvements to the Kirby Query language. Since the query language plays such an essential part for our blueprints, the new query improvements will push the possibilities for blueprints even further.
The improvements are based on a new AST-based query parser and runner that has been added in addition to the previous (legacy) parser. The legacy parser which will remain the default parser for now but we aim to replace it with the new runner in Kirby 6. Consider the new runner in beta state during Kirby 5.x releases. #6788
The new AST-based runner (thx to @rasteiner for starting off the work on this) runs not only more reliably and performant, but also allow us to add more functionalities. Those are not supported by the legacy runner.
- Support for more operators:
- Logic (
AND/&&/OR/||) - Compare (
==,!=,>,<,<=,>=) - Math (
+,-,*,/,%)
- Logic (
- Closures in queries can now accept arguments
- Queries support subscript access notation, e.g.
page[site.pageMethodName] query.runneroption to switch toKirby\Query\Runners\DefaultRunner::classto activate the new AST-based runner (See docs below for more information how to create a custom runner)
The new query runner is stricter in parsing queries. In some edge cases, this will require you to access an array/object via subscript notation - in rare cases on the top level via the new this keyword, e.g. this["indentifier.with dots and spaces"].
Batch delete for structures
New batch mode for structure fields to delete multiple rows at once. You can activate it by using the new batch option in your blueprint (#7400):
structure:
batch: true
fields:
text:
type: text
structures.mov
Searchable info in multiselect fields
You can now search through the info in a multiselect field by enabling the search > info option. (Thanks to @aofn) #7089
fields:
multiselect:
type: multiselect
options:
...
search:
info: true
Stats field
We’ve turned the stats section into an additional new field. The stats section keeps existing, but with the new stats field there are more layout possibilities and options for simpler blueprint setups. The field has the exact same options as the stats section (https://getkirby.com/docs/reference/panel/sections/stats). #7392
title: Shop
fields:
stats:
type: stats
size: huge
reports:
- label: Revenue
value: €29,682
info: +112.5%
link: https://getkirby.com/shop
theme: positive
- label: Orders
value: 265
info: +82.8%
theme: positive
- label: Avg. Transaction
value: €112.01
info: +16.3%
theme: positive
- label: Refunds
value: €15.20
info: +10.5%
theme: positive
- label: Discount sales
value: €1,422
info: n/aImagick thumb driver
New imagick thumbs driver, using the Imagick class instead of the convert command line command #6754
// /site/config/config.php
return [
'thumbs' => [
'driver' => 'imagick'
]
];Set the default panel.theme
You can now set the default Panel theme that is used when the user has not set any custom setting in their account view. Supported values: "light", "dark" or "system" (default, matches the user's operating system) #7341
// site/config/config.php
return [
'panel' => [
'theme' => 'light'
]
];New Collection::join() method
This new method is available in all collections #7340 (thx to @adamkiss)
$venues = $page->children()->join(' | ', fn ($child) => $child->venue());
$venues = $page->children()->join(as: fn ($child) => snippet('venue', ['page' => $child], return: true));New session.cookieDomain option
The option allows to share the session cookie across subdomains with a shared sessions folder feedback.getkirby.com/628
Note
You can read more about the behavior of the domain attribute for cookies in the MDN docs.
Note that setting the cookieDomain option disables Kirby setting the path attribute to the cookie (relevant in subfolder setups).
return [
'session' => [
'durationNormal' => 7200, // default: 2 hours
'durationLong' => 1209600, // default: 2 weeks
'timeout' => 1800, // default: half an hour
'cookieDomain' => 'getkirby.com', // default: automatic browser behavior
'cookieName' => 'kirby_session',
'gcInterval' => 100 // default: cleanup every ~100 requests
]
];Dialog search input improvements
The dialog search input has a new button to clear the input #7513
search.mov
Option to delete a license
The license dialog now includes a button to remove the license file #6962 [#6960](https://
✨ Enhancements
Support for nested dialogs
We've added history support for panel.dialog for nested dialogs #7519 Dialogs can now correctly open more dialogs which will be stacked on top of each other and close correctly.
Improved UI for the structure field
We've improved the UI when the structure field is disabled that allows to open drawer to see all fields as well as navigate through all entries when paginated https://feedback.getkirby.com/687
Improved language detector
Our language detector will now correctly detect languages based on locales. You can now easily set up two English locales (en_GB and en_US) for example and the detector will pick the right one and redirect correctly. (thanks to @tobiasfabian) #7178
Change the panel translation via URL
You can now set the Panel interface translation on demand with the new translation query parameter. E.g. https://example.com/panel/login?translation=it #6616
Better fatal view
We've added a link to the PHP version support table from the fatal view that is displayed on unsupported PHP versions
New skeleton theme for items
We've added a new sekeleton theme for the k-item component to represent a loading state #7521
Snippet controllers
With Kirby 5.1 you can create a small plugin that enables support for snippets and block controllers: one can add a controller for e.g. the snippet site/snippets/header.php to site/controllers/snippets/header.php. And since blocks are also just snippets, e.g. site/controllers/snippets/blocks/video.php.
As there can be many snippet calls within a single request, checking for the existence of a controller for each of these can impact your site’s performance.
<?php
use Kirby\Cms\App;
use Kirby\Template\Snippet;
use Kirby\Toolkit\Str;
class SnippetWithController extends Snippet
{
protected static $controllers = [];
public static function controller(
string|null $file,
array $data = []
): array {
if (
$file === null ||
str_starts_with($file, static::root()) === false
) {
return $data;
}
if (isset(static::$controllers[$file])) {
return array_replace_recursive(
$data,
static::$controllers[$file]
);
}
$name = ltrim(Str::before(Str::after($file, static::root()), '.php'), '/');
// if the snippet has a name, we can load the controller
// and merge the data with the controller's data
if ($name !== null) {
$data = array_replace_recursive(
$data,
static::$controllers[$file] = App::instance()->controller('snippets/' . $name, $data)
);
}
return $data;
}
public static function factory(
string|array|null $name,
array $data = [],
bool $slots = false
): static|string {
$file = $name !== null ? static::file($name) : null;
$data = static::controller($file, $data);
return parent::factory($name, $data, $slo...