Usage
Authentication
The Kirby Headless plugin exposes your content to the public by default. To secure your API, you can enable bearer token authentication for the KQL and custom API endpoints. This is especially useful for KQL requests, as Kirby's default KQL endpoint only supports basic authentication.
To enable bearer token authentication, set the headless.token
global option in your config.php
to a secret string:
return [
'headless' => [
'token' => 'test'
]
];
You will then need to include the HTTP header Authentication: Bearer {token}
with every request.
/api/kql
endpoint will always enforce bearer authentication, unless you explicitly disable it by setting the kql.auth
option to false
.Cross Origin Resource Sharing (CORS)
CORS issues are a common problem when fetching data from a different domain. To allow cross-origin requests, Kirby Headless responds with the appropriate CORS headers for preflight requests. You can customize the CORS configuration in your config.php
:
return [
'headless' => [
// Default CORS configuration
'cors' => [
'allowOrigin' => '*',
'allowMethods' => 'GET, POST, OPTIONS',
'allowHeaders' => 'Accept, Content-Type, Authorization, X-Language',
'maxAge' => '86400',
]
]
];
Kirby Query Language (KQL)
It is common to authenticate API requests with a token, which is not possible with the default KQL endpoint (/api/query
as defined by the official KQL plugin). To solve this problem, this plugin adds a new KQL endpoint under /api/kql
that supports the following features:
- Bearer token authentication
- Query response caching
- Multi-language support
To enable the bearer token authentication for KQL query requests to /api/kql
, set the following option in your config.php
:
return [
// Default to token-based authentication
'kql' => [
'auth' => 'bearer'
]
];
Now fetch the KQL query results as you normally would, but include an `Authentication' header with the bearer token in your request:
const response = await fetch("https://example.com/api/kql", {
method: "POST",
body: {
query: "site",
select: {
title: true,
photography: {
query: "page('photography').children",
select: ["title", "url"],
},
},
},
headers: {
Authentication: `Bearer ${process.env.KIRBY_API_TOKEN}`,
},
});
const data = await response.json();
console.log(data);
Basic Authentication for KQL
If you prefer the default basic authentication method, you can still enable it by setting the kql.auth
option to true
. This will disable bearer token authentication, but still provide features like caching and multi-language support:
return [
// Enable basic authentication for the Kirby API (required for KQL)
'api' => [
'basicAuth' => true
],
// Default to basic authentication
'kql' => [
'auth' => true
]
];
/api/query
always continues to use basic authentication and also derives the kql.auth
configuration option.Panel Configuration
Preview URL to the Frontend
If you're running a headless CMS, the default preview links from the Kirby Panel won't make much sense because they point to the backend URL. We need to change the hostname of the generated preview URLs to the frontend URL. To do this, set the preview
option in your template to a Kirby query that calls the frontendUrl
page method provided by this plugin:
options:
# Or `site.frontendUrl` for the `site.yml`
preview: "{{ page.frontendUrl }}"
Finally, set the frontendUrl
option in your config.php
:
return [
'headless' => [
'panel' => [
'frontendUrl' => 'https://example.com'
]
]
];
If the value is empty, the preview button will be disabled altogether.
Redirect to the Panel
If your Kirby project is headless only and no visual content is served, you may want to redirect editors to the Panel when they visit the backend. You could create a default template with a redirect, but it's easier to set the redirect
option in your config.php
:
return [
'headless' => [
'panel' => [
'redirect' => true
]
]
];
JSON Templates
When writing a Kirby template, it will be rendered as HTML by default. To opt-in to JSON templates, you can encode the template data as JSON and return it as a response. This is useful for headless setups where KQL is not sufficient or you want to control the data structure in PHP.
Kirby Headless doesn't interfere with Kirby's default routing. To overwrite Kirby's global routing to return JSON templates, set the globalRoutes
option in your config.php
:
return [
'headless' => [
'globalRoutes' => true
]
];
Template Example
Writing templates as JSON is straightforward. Here is an example of how to encode the data of an about
template as JSON:
$data = [
'title' => $page->title()->value(),
'layout' => $page->layout()->toLayouts()->toArray(),
'address' => $page->address()->value(),
'email' => $page->email()->value(),
'phone' => $page->phone()->value(),
'social' => $page->social()->toStructure()->toArray()
];
echo \Kirby\Data\Json::encode($data);
To fetch the JSON template data, you can use the following JavaScript example:
const response = await fetch("https://example.com/about", {
headers: {
Authentication: `Bearer ${process.env.KIRBY_API_TOKEN}`,
},
});
const data = await response.json();
console.log(data);