Releases: getkirby/kirby
5.3.1
✨ Enhancements
- Updated translation (tr)
🐛 Bug fixes
- Using
$users->find()with more than one argument or$field->toUsers()/$field->toUser()no longer results in unfiltered collections. #7943 - Calling
$users->find(false)no longer loads an invalid empty user object. #7952 $lazyCollection->prepend()and$users->prepend()ensure the intended element order even if the collection was not initialized before. #7952$lazyCollection->empty()and$users->empty()no longer result in populated collections if the original collection was not initialized before. #7952- Toggle field: Fixed duplicate display of field icon #7939
- Fixed styling of tags with icons (e.g. link field preview) #7938
- Fixed view button actions on the file view #7954
🧹 Housekeeping
- Add missing code comments on the behavior of
$collection->find(false, false, ...$data)#7952 - Updated CI config for backend tests
5.3.0
Caution
Unfortunately the Kirby 5.3.0 release introduced a regression in the user handling that leads to wrong results when using $users->find(), $field->toUsers() or $field->toUser(). All of these wrongly return the entire set of users without filtering.
Please update to Kirby 5.3.1 or later.
🎉 Features
- Support for option icons in checkboxes, multiselect, radio and tags field #7673



- New
<k-code-token>component and global styles for inline<code>elements withdata-typeattribute. The styles for the colored inline elements have been taken from our lab examples and are now available anywhere. The type can either be a generic type (string, float, bool, etc.) or a color keyword from our design system (green, red, orange, etc.) #7765

- New
<k-stack>component to help with horizontal and vertical layouts. Think of it as a flex layout helper component. It's perfect to create equal gaps between elements in a column or row. E.g. different sections or the gap between the headline and contents of a container. #7766

You can either use the component as a wrapper (which will create a div):… or use the k-stack class on an existing wrapper element to inherit the basic stack styles:<k-stack> <k-box theme="white">Test Box</k-box> <k-box theme="white">Test Box</k-box> <k-box theme="white">Test Box</k-box> </k-stack>
Use the attributes<ul class="k-stack"> <li>Item A</li> <li>Item B</li> <li>Item C</li> </ul>
gap,direction,alignandjustifyto control the layout.Those are applied as inline styles. If you use the<k-stack gap="var(--spacing-12)" align="center" direction="row" justify="space-between"> <k-box theme="white">Test Box</k-box> <k-box theme="white">Test Box</k-box> <k-box theme="white">Test Box</k-box> </k-stack>
k-stackclass on a custom element, you need to set the inline styles manually or with the CSS rules for your element. - New
<k-definitions>and<k-definition>components to build definition lists in the style of our tables. This is particularly useful to show any kind of information in a semantic way. We will use this for our new error dialogs. #7767
Definition items can also be created with custom slots:<k-definitions> <k-definition term="Term" description="Description" /> <k-definition term="Term" description="Description" /> <k-definition term="Term" description="Description" /> </k-definitions>
<k-definitions> <k-definition> <template #term><em>Term</em></template> <p class="k-text"> <a href="<https://getkirby.com>">Description</a> </p> </k-definition> <k-definition> <template #term><em>Term</em></template> <p class="k-text"> <a href="<https://getkirby.com>">Description</a> </p> </k-definition> <k-definition> <template #term><em>Term</em></template> <p class="k-text"> <a href="<https://getkirby.com>">Description</a> </p> </k-definition> </k-definitions>
- New
<k-checklist>component to create appealing lists of items that are marked as checked, to be noticed or errors. We will be using this in our new error dialogs, but the component is also very helpful for all kinds of scenarios in plugins and other parts of the Panel. #7771
Applying a theme:<k-checklist> <li>Item A</li> <li>Item B</li> <li>Item C</li> </k-checklist>
All color themes are supported.<k-checklist theme="negative"> <li>Item A</li> <li>Item B</li> <li>Item C</li> </k-checklist>
noticeandnegativewill automatically change the marker (see screenshot) You can easily add your own custom markers as well.<k-checklist style="--checklist-marker: '💛'"> <li>Item A</li> <li>Item B</li> <li>Item C</li> </k-checklist>
- New
Kirby\Http\Url::editor($editor, $file, $line)method, to create local editor URLs to open files in a code editor at the given line. #7768<a href="<?= Url::editor('vscode', '/my/local/file.php', 12) ?>">Open in VSCode</a>
- Preview view: Button to sync scrolling in the compare mode #7813
- New
scroll-to-bottomandscroll-to-bottom-fillicons #7813 - New
LazyCollectionclass that initializes and loads its data and elements only when they are first needed #7839
⚡Performance
- Improved performance of UUID enabled check #7094
- User credentials (main data from
index.php) are only loaded once when the user object is first created, improving system performance with many user accounts. - Significantly improved performance when large numbers of user accounts are set up #7841
✨ Enhancements
$visitor->ip()supports new$hashparameter to retrieve a 50 char long hash of the visitor's IP- More readable file paths in JSON error responses for the Panel. Absolute paths to the kirby folder, site folder and index folder will now be replaced with
{kirby},{site}and{index}. This will keep the responses more readable and easier to debug. It will also disguise the filesystem a bit. Although this is not the main intention, since those paths are only visible in debug mode anyway. #7772 - New
layout-top+layout-bottomicons #7814 - Child classes of
Iterator(mostly collections) can now implement a custom iterator and are not pinned toArrayIterator#7838 - New
User::hasPassword()method to provide a solid check for an existing password #7869 - The user dropdown now uses "Set password" instead of "Change password" for users that don't have a password so far. #7869

- Added support for view button separators using (thx @tobimori ) #7873
buttons:
- open
- preview
- '-'
- languages
- '-'
- settings- New
OfflineErrorerror type inkirby/panel/src/errors/OfflineError.js. kirby/panel/src/panel/request.jsnow usessafeFetch()and emits offline on network failures.kirby/panel/src/api/request.jsusessafeFetch()instead of rawfetch().kirby/panel/src/panel/panel.jscatchesOfflineErrorand setsisOffline.- Kirby now can handle HTTP range requests for partial content delivery #1207
- New
Filesystem\F::range($file, $offset, $length)method to only read parts of a file - New
Http\Rangeclass for handling HTTP range requests <k-drawer>has newsizeprop (options:tiny,small,default,large,huge) #7900<k-tag>: support foricon. #7886<k-checkboxes-input>,<k-radio-input>,<k-toggle-input>: support for additionaliconalongside text and info for the label #7886Kirby\Filesystem\F::load()has a newcacheparameter which will return the file content from cache or add the loaded file content to a cache on the first time its loaded #7920
🐛 Bug fixes
- Page move dialog: show spinner while loading https://feedback.getkirby.com/652
- Fixes broken selection state in textarea buttons if not initialized #7831
Iterator::has()and thehas()method of collections correctly treats an existing butnullvalue as a valid collection element #7838- UUID cache gets populated on model actions (e.g. page creation) #7809
- Users can now set their first password (if they had none so far) without providing their current one. This only works for their own account. A user without password cannot change the password of any other user. #7869
- Empty passwords are no longer incorrectly hashed #7869
A::get(): Prefer dotted prefix keys to avoid option collisions of full dotted pr...
6.0.0-alpha.2
TL;DR:
Kirby 6.0.0-alpha.2 is an early developer preview. We plan for a final release in the second half of 2026. Kirby 6 will be a free upgrade for all Kirby 4 & 5 license holders.
Important
Don't use Kirby 6 in production yet
Highlights
✍️ Live editor
📄 Simplified blueprint definition
🥞 New template stacks
🔘 New buttons field
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.2/CHANGELOG.md
5.3.0-rc.1
🎉 Features
- Support for option icons in checkboxes, multiselect, radio and tags field #7673



- New
<k-code-token>component and global styles for inline<code>elements withdata-typeattribute. The styles for the colored inline elements have been taken from our lab examples and are now available anywhere. The type can either be a generic type (string, float, bool, etc.) or a color keyword from our design system (green, red, orange, etc.) #7765

- New
<k-stack>component to help with horizontal and vertical layouts. Think of it as a flex layout helper component. It's perfect to create equal gaps between elements in a column or row. E.g. different sections or the gap between the headline and contents of a container. #7766

You can either use the component as a wrapper (which will create a div):… or use the k-stack class on an existing wrapper element to inherit the basic stack styles:<k-stack> <k-box theme="white">Test Box</k-box> <k-box theme="white">Test Box</k-box> <k-box theme="white">Test Box</k-box> </k-stack>
Use the attributes<ul class="k-stack"> <li>Item A</li> <li>Item B</li> <li>Item C</li> </ul>
gap,direction,alignandjustifyto control the layout.Those are applied as inline styles. If you use the<k-stack gap="var(--spacing-12)" align="center" direction="row" justify="space-between"> <k-box theme="white">Test Box</k-box> <k-box theme="white">Test Box</k-box> <k-box theme="white">Test Box</k-box> </k-stack>
k-stackclass on a custom element, you need to set the inline styles manually or with the CSS rules for your element. - New
<k-definitions>and<k-definition>components to build definition lists in the style of our tables. This is particularly useful to show any kind of information in a semantic way. We will use this for our new error dialogs. #7767
Definition items can also be created with custom slots:<k-definitions> <k-definition term="Term" description="Description" /> <k-definition term="Term" description="Description" /> <k-definition term="Term" description="Description" /> </k-definitions>
<k-definitions> <k-definition> <template #term><em>Term</em></template> <p class="k-text"> <a href="<https://getkirby.com>">Description</a> </p> </k-definition> <k-definition> <template #term><em>Term</em></template> <p class="k-text"> <a href="<https://getkirby.com>">Description</a> </p> </k-definition> <k-definition> <template #term><em>Term</em></template> <p class="k-text"> <a href="<https://getkirby.com>">Description</a> </p> </k-definition> </k-definitions>
- New
<k-checklist>component to create appealing lists of items that are marked as checked, to be noticed or errors. We will be using this in our new error dialogs, but the component is also very helpful for all kinds of scenarios in plugins and other parts of the Panel. #7771
Applying a theme:<k-checklist> <li>Item A</li> <li>Item B</li> <li>Item C</li> </k-checklist>
All color themes are supported.<k-checklist theme="negative"> <li>Item A</li> <li>Item B</li> <li>Item C</li> </k-checklist>
noticeandnegativewill automatically change the marker (see screenshot) You can easily add your own custom markers as well.<k-checklist style="--checklist-marker: '💛'"> <li>Item A</li> <li>Item B</li> <li>Item C</li> </k-checklist>
- New
Kirby\Http\Url::editor($editor, $file, $line)method, to create local editor URLs to open files in a code editor at the given line. #7768<a href="<?= Url::editor('vscode', '/my/local/file.php', 12) ?>">Open in VSCode</a>
- Preview view: Button to sync scrolling in the compare mode #7813
- New
scroll-to-bottomandscroll-to-bottom-fillicons #7813 - New
LazyCollectionclass that initializes and loads its data and elements only when they are first needed #7839
⚡Performance
- Improved performance of UUID enabled check #7094
- User credentials (main data from
index.php) are only loaded once when the user object is first created, improving system performance with many user accounts. - Significantly improved performance when large numbers of user accounts are set up #7841
✨ Enhancements
$visitor->ip()supports new$hashparameter to retrieve a 50 char long hash of the visitor's IP- More readable file paths in JSON error responses for the Panel. Absolute paths to the kirby folder, site folder and index folder will now be replaced with
{kirby},{site}and{index}. This will keep the responses more readable and easier to debug. It will also disguise the filesystem a bit. Although this is not the main intention, since those paths are only visible in debug mode anyway. #7772 - New
layout-top+layout-bottomicons #7814 - Child classes of
Iterator(mostly collections) can now implement a custom iterator and are not pinned toArrayIterator#7838 - New
User::hasPassword()method to provide a solid check for an existing password #7869 - The user dropdown now uses "Set password" instead of "Change password" for users that don't have a password so far. #7869

- Added support for view button separators using (thx @tobimori ) #7873
buttons:
- open
- preview
- '-'
- languages
- '-'
- settings- New
OfflineErrorerror type inkirby/panel/src/errors/OfflineError.js. kirby/panel/src/panel/request.jsnow usessafeFetch()and emits offline on network failures.kirby/panel/src/api/request.jsusessafeFetch()instead of rawfetch().kirby/panel/src/panel/panel.jscatchesOfflineErrorand setsisOffline.- Kirby now can handle HTTP range requests for partial content delivery #1207
- New
Filesystem\F::range($file, $offset, $length)method to only read parts of a file - New
Http\Rangeclass for handling HTTP range requests <k-drawer>has newsizeprop (options:tiny,small,default,large,huge) #7900<k-tag>: support foricon. #7886<k-checkboxes-input>,<k-radio-input>,<k-toggle-input>: support for additionaliconalongside text and info for the label #7886Kirby\Filesystem\F::load()has a newcacheparameter which will return the file content from cache or add the loaded file content to a cache on the first time its loaded #7920
🐛 Bug fixes
- Page move dialog: show spinner while loading https://feedback.getkirby.com/652
- Fixes broken selection state in textarea buttons if not initialized #7831
Iterator::has()and thehas()method of collections correctly treats an existing butnullvalue as a valid collection element #7838- UUID cache gets populated on model actions (e.g. page creation) #7809
- Users can now set their first password (if they had none so far) without providing their current one. This only works for their own account. A user without password cannot change the password of any other user. #7869
- Empty passwords are no longer incorrectly hashed #7869
A::get(): Prefer dotted prefix keys to avoid option collisions of full dotted prefix vs. nested array, e.g. with plugin options #6242- Radio input: Fixed resetting via clicking the input label #5845
- Options from query: if the query returns an associative array, Kirby now uses the array keys as values by default [#5807](https://github.com/getkirby/kirby/issue...
5.2.3
🐛 Bug fixes
- Using page title in string template of other fields #7834
- Writer Text field cannot handle multi-domain multi-language page links #7786
- The time field does now submit the form when pressing enter. #774
- Fixed console error for skipped page create dialogs #7877
- Fixed "Change Template" options for files: All available file templates are shown when sections don't define available templates #6761
- Fixed opening TOTP disable dialog #7895
- Thumb jobs files do not get regenerate if they already exist #7861
- Blocks field
5.2.2
Caution
🚨 Security
Missing permission checks in the content changes API
CVE ID: CVE-2026-21896
Severity: medium (CVSS score 5.8)
This vulnerability affects all Kirby sites (Kirby 5.0.0-5.2.1) where user permissions are configured to prevent specific role(s) from performing write actions, specifically by disabling the update permission with the intent to prevent modifications to site content.
If you haven't configured any user permissions that deviate from the default of allowing all actions, your site is not affected.
🐛 Bug fixes
- Prevent error when calling
Remote::json()with single-value JSON content (e.g. a single string, single int) #7806 - Fixed
Kirby\Toolkit\Domfor newer libxml versions #7802 - Writer field: fixed inline toolbar position on views without Panel menu #7799
$collection->group(callable)should accept empty string result as key #7830- Fixed filename field bug in upload dialog #7662
♻️ Refactored
- Reset
$_SERVERmanipulation in tests #7807
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...