Traversing content outside of templates

I’m re-creating a client’s wordpress site using Kirby. To do this, I’m using (huge) XML files I exported from wordpress, parse them in PHP, and using that data to build the Kirby site’s content folder.

I’m doing this with a PHP script that is outside of any kirby directories - /scripts/parse.php

This is working for the first round, creating pages for each author -


// load kirby
require($_SERVER['DOCUMENT_ROOT'] . DS . 'kirby' . DS . 'bootstrap.php');

// all of my XML parsing, builds an $authors[] array

foreach ($authors as $author) {

  try {
    $newPage = page('writers')->children()->create($uid, 'writer', $writer_arr);
    echo "<span style='color:blue'>The page " . $writer_arr['title'] . " has been created</span>";
  catch(Exception $e) {
    echo $e->getMessage();


The next round is to input all of the data for the books. I tried:

 $newPage = page('writers')->children()->find($author_uid)->create($book_uid, 'writer', $book_arr);

But, this won’t work. Trying to do anything with $pages->... returns an undefined error.

I was able to solve this by creating /content/parse/parse.txt and moving my script to a parse.php template. Once I’m working “in” the content, it works as expected.

But, is there a way to dig into this without the PHP being in a template?

Maybe this helps:

1 Like

That’s exactly what I was looking for! I searched github and this forum - I didn’t think to check the old one.
Since it’s not going to be around forever I’ll paste in the relevant post:

Method 1

require_once "kirby/toolkit/vendors/yaml/yaml.php";              // Kirby's built-in YAML parser based from Spyc
$Data = spyc_load_file('content/site.txt');              // loads the file to be parsed by this parser
echo $Data['Title'];              // outputs      "Kirby Starter Kit"

Method 1 parses the site.txt file directly to get values.



// load kirby
require(DIR . DS . 'kirby' . DS . 'bootstrap.php');

$kirby = kirby();
$site = $kirby->site();

Method 2 uses kirby’s syntax to get the value. This is an official answer from Bastian, this is why it’s recommended, however, you can use either of the two.

All the best,
Phoenix Peca


Very useful.
I’m loading kirby from a file in assets/php/ like this:

require("..". DS ."..". DS .'kirby'. DS .'bootstrap.php');

Accessing pages’ data works fine, but I have these problems:

  • I can’t access language-specific variables like l::get('foo')

  • $site->url() returns the url of the current php file, instead of the base folder of the site

You would have to load the language files manually, I guess;

But you’d still have the problem that you need to tell Kirby what the correct language is, as that is not known to Kirby if you just load the bootstrapped. May I ask what your use case is for loading Kirby from the assets folder?

Thx for your quick reply.
I have a script that generates some html for a modal. The script is called with AJAX on modal launch.
I found it difficult to use a snippet in this case, so I just created an “external” file and placed it in the assets folder.

I’d do this via a route, then call the route in your Ajax call. However, you’d still have to call your language files within the route.

Yeah, that works perfectly! I’ll post the code maybe it will be useful to someone.

c::set('routes', array(
    'pattern' => 'api/modal-dg/(:any)/(:any)',
    'action' => function ($id, $lang) {
      // load the appropriate language file
      require_once(kirby()->roots()->languages() ."/$lang.php");
      // call the snippet returning its value into a variable
      $html = snippet('modal-dg', [
        'id'    => $id,
        'lang'  => $lang
      ], true);

      // return the resulting html using a response object
      return new Response($html);