johannschopplich/kirby-headless

API-first toolkit for Kirby CMS

Maintainers

Package info

github.com/johannschopplich/kirby-headless

Homepage

Type:kirby-plugin

pkg:composer/johannschopplich/kirby-headless

Fund package maintenance!

paypal.me/jschopplich

Statistics

Installs: 16 081

Dependents: 0

Suggesters: 0

Stars: 43

Open Issues: 0

7.0.0 2026-06-14 20:49 UTC

README

Kirby Headless logo

Kirby Headless

Bearer-authenticated KQL, UUID resolution in blocks and layouts, JSON templates, and an Express-style API builder for Kirby – everything you need to drive any frontend from Kirby.

KQLField MethodsJSON TemplatesAPI BuilderAuthentication

Note

Want a ready-to-use headless-only project? Start from the Kirby Headless Starter.

When to Use

I want to… Use
Query content from a frontend over HTTP KQL endpoint at /api/kql
Lock the API behind a token instead of basic auth kql.auth => 'bearer' + headless.token
Resolve UUIDs in blocks and layouts to real objects $field->toResolvedBlocks()
Resolve permalinks in writer and text fields $field->resolvePermalinks()
Return JSON straight from a template JSON templates / __template__ endpoint
Compose custom, authenticated API routes Api::createHandler() + middlewares
Build navigation and language switchers in the frontend page methods (frontendUrl(), i18nMeta(), …)

Features

🔑 Bearer Token Authentication

Protect the /api/kql endpoint and your own API routes with a bearer token, or fall back to Kirby's native API authentication.

// config.php
return [
    'kql' => ['auth' => 'bearer'],
    'headless' => ['token' => 'your-secret-token']
];

Read more →

🧱 Block & Layout Resolution

Resolve UUIDs in blocks and layouts to complete file and page objects server-side, so your frontend consumes ready-to-use URLs and data. Configure which fields to resolve, or plug in custom resolvers.

$page->blocks()->toResolvedBlocks()->toArray();
$page->layout()->toResolvedLayouts()->toArray();

Read more →

⚡️ Enhanced KQL

A drop-in /api/kql endpoint that extends the official KQL plugin with bearer authentication, response caching, and multi-language support via a request header.

await fetch("https://example.com/api/kql", {
  method: "POST",
  headers: { Authorization: `Bearer ${token}` },
  body: JSON.stringify({ query: "page('notes').children" }),
});

Read more →

🗂 JSON Templates

Return JSON from your templates instead of HTML for full control over the response shape, with built-in __template__ and __sitemap__ endpoints.

// site/templates/about.php
echo \Kirby\Data\Json::encode([
    'title' => $page->title()->value(),
    'layout' => $page->layout()->toResolvedLayouts()->toArray()
]);

Read more →

🍢 API Builder

Compose routes from middleware chains – Express-style. Reuse bearer auth, file and page resolution, or your own validators across routes.

use JohannSchopplich\Headless\Api\Api;
use JohannSchopplich\Headless\Api\Middlewares;

Api::createHandler(
    Middlewares::hasBearerToken(),
    fn (array $context, array $args) => Api::createResponse(200, [
        'message' => 'Hello World'
    ])
);

Read more →

🧭 Page Methods

Helpers for headless frontends: frontend URLs, breadcrumb data, and multi-language metadata for navigation and language switchers.

$page->frontendUrl();    // URL on your frontend app
$page->breadcrumbMeta(); // breadcrumb data for navigation
$page->i18nMeta();       // language switcher metadata

Read more →

Requirements

  • Kirby 5
  • PHP 8.3+

Note

Using Kirby 4? Install the v4 release.

Installation

Composer (Recommended)

composer require johannschopplich/kirby-headless

Manual Installation

Download and copy this repository to /site/plugins/kirby-headless.

License

MIT License © 2022-PRESENT Johann Schopplich