Skip to content

Releases: getkirby/kirby

5.3.1

16 Feb 19:46
0ccfcab

Choose a tag to compare

✨ 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

10 Feb 12:31
3e14463

Choose a tag to compare

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
    image
    image
    image
  • New <k-code-token> component and global styles for inline <code> elements with data-type attribute. 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
    image
  • 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
    image
    You can either use the component as a wrapper (which will create a div):
    <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>    
    … or use the k-stack class on an existing wrapper element to inherit the basic stack styles:
    <ul class="k-stack">
    	<li>Item A</li>
    	<li>Item B</li>
    	<li>Item C</li>
    </ul>    
    Use the attributes gap, direction, align and justify to control the layout.
    <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>    
    Those are applied as inline styles. If you use the k-stack class 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
    image
    <k-definitions>
    	<k-definition term="Term" description="Description" />
    	<k-definition term="Term" description="Description" />
    	<k-definition term="Term" description="Description" />
    </k-definitions>    
    Definition items can also be created with custom slots:
    <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
    image
    <k-checklist>
    	<li>Item A</li>
    	<li>Item B</li>
    	<li>Item C</li>
    </k-checklist>
    Applying a theme:
    <k-checklist theme="negative">
    	<li>Item A</li>
    	<li>Item B</li>
    	<li>Item C</li>
    </k-checklist>
    All color themes are supported. notice and negative will 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-bottom and scroll-to-bottom-fill icons #7813
  • New LazyCollection class 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 $hash parameter 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-bottom icons #7814
  • Child classes of Iterator (mostly collections) can now implement a custom iterator and are not pinned to ArrayIterator #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
    image
  • Added support for view button separators using (thx @tobimori ) #7873
buttons:
  - open
  - preview
  - '-'
  - languages
  - '-'
  - settings
  • New OfflineError error type in kirby/panel/src/errors/OfflineError.js.
  • kirby/panel/src/panel/request.js now uses safeFetch() and emits offline on network failures.
  • kirby/panel/src/api/request.js uses safeFetch() instead of raw fetch().
  • kirby/panel/src/panel/panel.js catches OfflineError and sets isOffline.
  • 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\Range class for handling HTTP range requests
  • <k-drawer> has new size prop (options: tiny, small, default, large, huge) #7900
  • <k-tag>: support for icon. #7886
  • <k-checkboxes-input>, <k-radio-input>, <k-toggle-input>: support for additional icon alongside text and info for the label #7886
  • Kirby\Filesystem\F::load() has a new cache parameter 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 the has() method of collections correctly treats an existing but null value 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...
Read more

6.0.0-alpha.2

04 Feb 12:30
d960733

Choose a tag to compare

6.0.0-alpha.2 Pre-release
Pre-release

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

03 Feb 11:10
38205e9

Choose a tag to compare

5.3.0-rc.1 Pre-release
Pre-release

🎉 Features

  • Support for option icons in checkboxes, multiselect, radio and tags field #7673
    image
    image
    image
  • New <k-code-token> component and global styles for inline <code> elements with data-type attribute. 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
    image
  • 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
    image
    You can either use the component as a wrapper (which will create a div):
    <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>    
    … or use the k-stack class on an existing wrapper element to inherit the basic stack styles:
    <ul class="k-stack">
    	<li>Item A</li>
    	<li>Item B</li>
    	<li>Item C</li>
    </ul>    
    Use the attributes gap, direction, align and justify to control the layout.
    <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>    
    Those are applied as inline styles. If you use the k-stack class 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
    image
    <k-definitions>
    	<k-definition term="Term" description="Description" />
    	<k-definition term="Term" description="Description" />
    	<k-definition term="Term" description="Description" />
    </k-definitions>    
    Definition items can also be created with custom slots:
    <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
    image
    <k-checklist>
    	<li>Item A</li>
    	<li>Item B</li>
    	<li>Item C</li>
    </k-checklist>
    Applying a theme:
    <k-checklist theme="negative">
    	<li>Item A</li>
    	<li>Item B</li>
    	<li>Item C</li>
    </k-checklist>
    All color themes are supported. notice and negative will 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-bottom and scroll-to-bottom-fill icons #7813
  • New LazyCollection class 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 $hash parameter 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-bottom icons #7814
  • Child classes of Iterator (mostly collections) can now implement a custom iterator and are not pinned to ArrayIterator #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
    image
  • Added support for view button separators using (thx @tobimori ) #7873
buttons:
  - open
  - preview
  - '-'
  - languages
  - '-'
  - settings
  • New OfflineError error type in kirby/panel/src/errors/OfflineError.js.
  • kirby/panel/src/panel/request.js now uses safeFetch() and emits offline on network failures.
  • kirby/panel/src/api/request.js uses safeFetch() instead of raw fetch().
  • kirby/panel/src/panel/panel.js catches OfflineError and sets isOffline.
  • 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\Range class for handling HTTP range requests
  • <k-drawer> has new size prop (options: tiny, small, default, large, huge) #7900
  • <k-tag>: support for icon. #7886
  • <k-checkboxes-input>, <k-radio-input>, <k-toggle-input>: support for additional icon alongside text and info for the label #7886
  • Kirby\Filesystem\F::load() has a new cache parameter 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 the has() method of collections correctly treats an existing but null value 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...
Read more

5.2.3

03 Feb 10:31
a7697cd

Choose a tag to compare

🐛 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
    • Fixed options toolbar position when open #7637
    • Deselect blocks when focus moves to an element outside of the blocks field #6599
    • Fix blocks becoming unresponsive when external apps steal focus #7914 (thx @tobimori)

5.2.2

08 Jan 10:50
55563aa

Choose a tag to compare

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\Dom for 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 $_SERVER manipulation in tests #7807

5.2.1

16 Dec 09:28
42cd286

Choose a tag to compare

✨ Enhancements

  • Updated translation (pt_PT)

🐛 Bug fixes

  • Fixed PHP 8.5 compatibility issues around files in the Panel #7773
  • Fixed a broken check for Page duplicates #7761

🧹 Housekeeping

  • Updated JS dependencies

6.0.0-alpha.1 – Developer Preview

09 Dec 11:40
c9a3012

Choose a tag to compare

Pre-release

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?

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

09 Dec 11:50
442466c

Choose a tag to compare

🤩 Highlights

  • 🐘 PHP 8.5 support
  • 📻 CORS support
  • ☑️ New batch select mode for the checkboxes field
  • ↕️ Collapse / expand all blocks
  • 📂 New create option 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

  1. Simple setup: Set 'cors' => true to enable CORS with sensible defaults. Check below for additional configuration options.
  2. Automatic preflight handling: When CORS is enabled, all OPTIONS CORS preflight requests automatically receive a 204 No Content response with appropriate CORS headers.
  3. 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.
  4. Vary header management (Hono inspired):
    • Wildcard origins (*): No Vary: Origin header is added (cache-efficient since response is identical for all origins)
    • Specific origins: Automatic Vary: Origin header ensures different origins are cached separately
    • Header reflection: Automatic Vary: Access-Control-Request-Headers for preflight requests when reflection is enabled
    • Auth/Cookie tracking: Automatic Vary: Authorization, Cookie when response uses authentication or cookies
    • Smart merging: All Vary values are combined intelligently without duplication
  5. Header reflection opt-in: With 'allowHeaders' => true, preflight requests mirror the headers requested by the client while Vary: Access-Control-Request-Headers ensures 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' => true lets 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: true
checkboxes.mp4

Thanks to this new feature, we now also have the following additions:

  • New select-all and deselect-all icons
  • New select.all, deselect.all and deselect translation 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

collapse-all

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: false

Better 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: files

The 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: files

This 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.com directory if plugin is listed there #7243
  • View button: `opti...
Read more

5.2.0-rc.1

02 Dec 11:07
a4784a4

Choose a tag to compare

5.2.0-rc.1 Pre-release
Pre-release

🤩 Highlights

  • 🐘 PHP 8.5 support
  • 📻 CORS support
  • ☑️ New batch select mode for the checkboxes field
  • ↕️ Collapse / expand all blocks
  • 📂 New create option 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

  1. Simple setup: Set 'cors' => true to enable CORS with sensible defaults. Check below for additional configuration options.
  2. Automatic preflight handling: When CORS is enabled, all OPTIONS CORS preflight requests automatically receive a 204 No Content response with appropriate CORS headers.
  3. 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.
  4. Vary header management (Hono inspired):
    • Wildcard origins (*): No Vary: Origin header is added (cache-efficient since response is identical for all origins)
    • Specific origins: Automatic Vary: Origin header ensures different origins are cached separately
    • Header reflection: Automatic Vary: Access-Control-Request-Headers for preflight requests when reflection is enabled
    • Auth/Cookie tracking: Automatic Vary: Authorization, Cookie when response uses authentication or cookies
    • Smart merging: All Vary values are combined intelligently without duplication
  5. Header reflection opt-in: With 'allowHeaders' => true, preflight requests mirror the headers requested by the client while Vary: Access-Control-Request-Headers ensures 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' => true lets 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: true
checkboxes.mp4

Thanks to this new feature, we now also have the following additions:

  • New select-all and deselect-all icons
  • New select.all, deselect.all and deselect translation 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

collapse-all

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: false

Better 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: files

The 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: files

This 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.com directory if plugin is listed there #7243
  • View button: `opti...
Read more