JSON Templates

Return JSON from Kirby templates for full control over your API responses.

JSON templates provide full control over your API responses in PHP. This is useful when KQL is not flexible enough or you need custom data structures.

Global Routes

By default, Kirby Headless does not interfere with Kirby's routing. Enable global routes to automatically return JSON from all templates:

config.php
return [
    'headless' => [
        'globalRoutes' => true
    ]
];
Enabling global routes overrides Kirby's default routing. All templates will return JSON instead of HTML.

Writing JSON Templates

Encode template data as JSON in your template files:

site/templates/about.php
<?php

$data = [
    'title' => $page->title()->value(),
    'layout' => $page->layout()->toResolvedLayouts()->toArray(),
    'address' => $page->address()->value(),
    'email' => $page->email()->value(),
    'phone' => $page->phone()->value(),
    'social' => $page->social()->toStructure()->toArray()
];

echo \Kirby\Data\Json::encode($data);

Fetching Template Data

Fetch JSON template data with bearer token authentication:

const response = await fetch("https://example.com/about", {
  headers: {
    Authorization: `Bearer ${process.env.KIRBY_API_TOKEN}`,
  },
});

const data = await response.json();

Template Routes

You can also fetch templates by name using the __template__ endpoint:

const response = await fetch("https://example.com/__template__/about", {
  headers: {
    Authorization: `Bearer ${process.env.KIRBY_API_TOKEN}`,
  },
});

const data = await response.json();

This fetches the about template and returns its JSON output.

Sitemap Endpoint

Kirby Headless includes a built-in sitemap endpoint at __sitemap__ that returns all indexable pages:

const response = await fetch("https://example.com/__sitemap__", {
  headers: {
    Authorization: `Bearer ${process.env.KIRBY_API_TOKEN}`,
  },
});

const sitemap = await response.json();

Sitemap Configuration

Configure which pages appear in the sitemap:

config.php
return [
    'headless' => [
        'sitemap' => [
            // Exclude templates from sitemap
            'exclude' => [
                'templates' => ['error', 'maintenance'],
                // Exclude pages by ID
                'pages' => ['home/draft-page']
            ],
            // Custom indexability check
            'isIndexable' => function ($page) {
                return $page->isListed() && $page->isPublic()->toBool();
            }
        ]
    ]
];