Headless CMS
Toolkit for Kirby

Everything you need to use Kirby as a headless content backend. Query content via KQL, build custom API routes, and resolve blocks – all with zero-config defaults.

Query Content with
KQL

Use Kirby's Query Language via a dedicated API endpoint. Built-in response caching and multi-language support included.
  • Bearer Token Auth
    Secure your API with modern token-based authentication
  • Automatic Caching
    Query responses are cached out of the box
curl https://example.com/api/kql \
  -H "Authorization: Bearer your-token" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "page(\"blog\").children.listed",
    "select": {
      "title": true,
      "text": "page.text.toBlocks.toArray",
      "url": true
    }
  }'

Headless Features

Bearer Token Auth
Modern authentication for API endpoints. Drop-in replacement for basic auth with configurable tokens.
KQL Endpoint
Query content via Kirby Query Language with automatic response caching and multi-language support.
JSON Templates
Return JSON from Kirby templates. Enable global routes to serve all content as structured data.
Resolved Blocks
Automatically resolve UUIDs in block and layout fields to complete file and page objects.
API Builder
Express-style API builder with middleware support for custom routes and authentication.
CORS Support
Delegates to Kirby's native CORS handling for cross-origin requests out of the box.

Build Custom Routes with the
API Builder

Define API routes with an Express-style middleware pattern. Chain authentication, validation, and response logic.
  • Middleware Support
    Composable middleware functions for auth, validation, and more
  • Consistent Responses
    Built-in JSON response format for all API routes
site/config/config.php
use JohannSchopplich\Headless\Api\Api;
use JohannSchopplich\Headless\Api\Middlewares;

return [
    'routes' => [
        [
            'pattern' => '__api__/login',
            'method' => 'POST',
            'action' => Api::createHandler(
                [Middlewares::hasBearerToken()],
                function ($context) {
                    $body = $context['body'];
                    $user = kirby()->user($body['email']);
                    return Api::createResponse(200, [
                        'user' => $user->email(),
                    ]);
                }
            ),
        ],
    ],
];

Free Forever. Open Source.

Install the Headless plugin and start building modern frontend applications with Kirby as your content backend.