Kirby 3 as Headless CMS for Vue/Nuxt

  1. No, no argument at all…just confirming what it is like :wink: I’m sure there’s a good reason for it.
  2. No, no yet, as I’m not sure it’s a bug. Is it? Or maybe we’re doing something wrong?
1 Like

to reinstate the point that confused some of us who posted on this thread:

being logged-in, whether by actually logging in to the /panel or by sending the user credentials with an API call to kirby is fine. in eg, you want kirby to be a headless cms, and your custom app interacts with the data from kirby in order to change it as well.

the confusion imho arises when understanding REST APIs as also only a way to read the data from an endpoint and use it to make an interface with it. in this case, it feels out of place to have to be logged in to the panel. or rather, if there’s an option to login to kirby through an API call as well, then i think my problems are solved :sunny:

i am up to open a ticket on github if it makes it easier to discuss!

Surely using a data representation would be a better more reliable way to do what you’re trying to do?

Main issue I would see about hooking into the panel endpoints are there is no guarantee that they won’t change with future versions of Kirby.

https://getkirby.com/docs/cookbook/templating/generating-json

Have a look at https://getkirby.com/docs/reference/api/auth/login

I cannot guarantee this 100%, but in general we see the API as something for people to use as well. Not just internally for us to communicate between core and panel. So we wouldn’t just change the endpoints completely erratic but we have others in mind.

That said, I’d also go for content representations. Mainly also because that way you much clearer can define who gets which data.

1 Like

then i think it makes sense to keep working on plugins like these Spad: Site to json plugin

:slight_smile:

Why not do it native as mentioned in my link above?

Thats a fair point, my thought could be although the intention is good, it does make it harder for you as the core team to maintain if you need to make breaking changes.

I understand your thinking, but it offers nothing over content representations.

i think it comes down to have to make a content representation template for each template of the website, versus having a plugin that scans your entire /content folder and does the same thing in one go.

but as there are still some limitations with the mentioned plugin due to the new version of kirby, it might indeed be more future-proof to set up the content-representation template yourself…

i’m looking forward to some headless cms / spas use cases though :slight_smile:

Why not use params to query into the represenation?

We’ve found the Kirby 3 API and Nuxt to be a great mix, but there are a few parts of the process that need some work.

You’ll probably need to use basic auth for API requests, as your Nuxt/Vue/SPA app may not have easy access to the CSRF field.

See here for how to enable basic auth in your Kirby config https://getkirby.com/docs/guide/api/authentication#http-basic-auth

Second hurdle is that currently Kirby will drop any basic auth API request if it is done without HTTPS. There’s some discussions and pending updates to Kirby that will hopefully resolve this, but for now I am manually patching my Kirby 3 sites to allow non-HTTPS API requests with basic auth.

I create a specific API-only Kirby user in my site. You may need to give this API-specific user reduced permissions. Be aware that a crafty user could reverse the email/password from the API and log in to your panel with the API account if this is used client side.

You might create a Kirby role called api (see Kirby permissions documentation)

Comment out these three lines in your Kirby src/Cms/Auth.php file https://github.com/getkirby/kirby/blob/72f01eac0a7db59360894e0cfb44680276260174/src/Cms/Auth.php#L73-L75

Once you’ve done that your API should work in development. Here’s a snippet of code for setting up the API in your JS app with axios (this will work on the client or server).

const axios = require('axios')

const kirbyEmail = 'api@yoursite.com'
const kirbyPassword = 'api-specific-password'
const kirbyBase = 'http://localhost:8888/kirby-site/api'

const authorization = Buffer.from([
  kirbyEmail,
  kirbyPassword
].join(':')).toString('base64')

const api = axios.create({
  baseURL: kirbyBase,
  headers: {
    Authorization: `Basic ${authorization}`
  }
})

From there, consuming the API in javascript-world looks like:

const res = await api.get('/pages/home')
const page = res.data

I’m working on a Nuxt module for this that will make things simpler. There’s potential to improve the process and support lots of developers wanting to build with Nuxt and the Kirby API.

6 Likes

As mentioned elsewhere the other hurdle to building sites this way is that the API returns raw kirbytext/markdown for text fields.

I’ve got a basic kirbytext to HTML parser that would be helpful but it needs some work.

@mattlenz I have been putting things in place for the same, you sound further ahead, want to work together on this?

Without having read all the replies, heres a website using Kirby 3 as headless CMS with a Nuxt.js Frontend:


It’s definitely takes a bit of effort to setup, but works great!

3 Likes

Do you serve your local server with a https certificate?

Somewhat solved this with a custom endpoint: https://github.com/robinscholz/CYMB_Backend/blob/master/site/config/config.php

I am looking through the code, but cant see if you are. How you handle kirbytext?

The custom endpoint converts kirbytags:

function kt($array) {
  foreach ($array as $key => $value) {
    if (is_array($value)) {
      $array[$key] = kt($value);
    } else {
      $array[$key] = kirbytags($value);
    }
 }
  return $array;
}

You could probably do the same for kirbytext, though with some more sophisticated code.
Somehow you’d need to figure out which fields to convert and which to leave untouched. Otherwise every field might get wrapped in <p> tags.

That would mean sending HTML over the API response?

Sure, if you parse it server side, you will have to.