Add information to virtual pages from API and combining with pages created in panel

Hey Kirby community,

I am getting virtual pages made from an API, but the API does not provide all the info that I need. I want to add additional information to virtual pages in the panel and then have the virtual pages and regular pages be siblings. I have read and tried to implement the solution here: Merging content sources | Kirby but uses CSV to make pages instead of an API, so it is a bit different.

Also, is it possible to add translations to virtual pages created from an API?

Here is where I’m at so far

public function subpages()
    {
        return Pages::factory($this->inventory()['children'], $this);
    }

public function children()
{
    $results = [];
    $pages   = [];
    $apiKey  = 'apikey';
    $request = Remote::get('https://getapi.com/results?token=' . $apiKey);

    if ($request->code() === 200) {
        $results = json_decode($request->content(), true);
    }

    foreach ($results as $key => $bonus) {
        // dump($bonus); dump('asdf');
        $pages[] = [
            'slug'     => Str::slug($bonus['brand']),
            'num'      => $key+1,
            'template' => 'bonus',
            'model'    => 'bonus',
            'content'  => [
                'title'    => $bonus['brand'],
                // 'headline' => $bonus->headline,
                // 'byline'   => $bonus->byline,
                // 'summary'  => $bonus->summary_short,
                // 'date'     => $bonus->publication_date,
                // 'link'     => $bonus->link->url,
                // 'linkText' => $bonus->link->suggested_link_text,
                // 'cover'    => $bonus->multimedia->src
            ]
        ];
    }

    // $dump = dump($results);

    // return $dump;

    return Pages::factory($pages, $this);
}

}

Thank you all for your help :slight_smile:

It doesn’t matter where the data comes from:

public function children()
{
         $results = [];
         $pages   = [];
         $apiKey  = 'apikey';
         $request = Remote::get('https://getapi.com/results?token=' . $apiKey);

         if ($request->code() === 200) {
            $results = json_decode($request->content(), true);
         }   
         $children = array_map(function ($bonus) {

            $slug  = Str::slug($bonus['brand']);
            $page = $this->subpages()->find($slug);

            return [
                'slug'     => $slug,
                'template' => 'bonus',
                'model'    => 'bonus',
                'content'  => [
                   'title'    => $bonus['brand'],
                    'commonName'  => $animal['Common Name'],
                    // 'headline' => $bonus->headline,
                    // 'byline'   => $bonus->byline,
                    // 'summary'  => $bonus->summary_short,
                    // 'date'     => $bonus->publication_date,
                    // 'link'     => $bonus->link->url,
                    // 'linkText' => $bonus->link->suggested_link_text,
                    // 'cover'    => $bonus->multimedia->src
                ]
            ];
        }, $results);

        return Pages::factory($children, $this);
    }

You mean locally in the file system? No idea…

Thanks for the solution; I implemented this example. Having a weird bug where I will save something on one of the virtual, hybrid pages and the change shows up in the “content” folder, but it does not show up in the panel. Whenever I create a page as a sibling of the virtual pages, it is deleted almost instantly. Any idea what could be causing these issues?

I may have found a solution. If you first make a page in Kirby (therefore it would be saved in the content folder), would you then be able to add in some content from an API into the existing fields while being able to add in additional content via the panel?

Hm, the guide was written based on the code we use on the getkirby.com website, where we don’t use the Panel. There is virtual content from the Reflections class to which we add additional examples etc, but as I said, all without the Panel so I never actually checked that out. But theoretically, storing stuff should work.

Have a look at this post I did a few months ago :

What I learnt from this technique: the subpages() function can be very slow with a lot of content and almost kill the back-end from loading.

I’m planning on caching the API, so hopefully, I can import all the content needed into the “content” folder and then only do an API call once a day or so. That would probably fix the slow loading in this case.

You can save from the panel, but you have to relist all the existing blueprints for the page in the model, which is a bit tedious. See “seoDescription” in the example, is there any way to avoid having to relist all of the previous existing page blueprints?)

return [
                'slug'     => $slug,
                'num'      => 0,
                'template' => 'bonus',
                'model'    => 'bonus',
                'content'  => [
                   'title'    => $bonus['brand'],
                   'seoDescription'   => $page ? $page->seoDescription()->value() : null
                    // 'commonName'  => $animal['Common Name'],
                    // 'headline' => $bonus->headline,
                    // 'byline'   => $bonus->byline,
                    // 'summary'  => $bonus->summary_short,
                    // 'date'     => $bonus->publication_date,
                    // 'link'     => $bonus->link->url,
                    // 'linkText' => $bonus->link->suggested_link_text,
                    // 'cover'    => $bonus->multimedia->src
                ]
            ];

I had also some cache setup using the Kirby plugin cache but what was slow was to parse and merge all the data (local and virtual) into one big Pages::factory().
With a powerful dedicated server with a lot of RAM it got faster, but I would suggest to be careful if you have a big amount of pages.

You mean the content fields, I guess. Yes, you need to inform Kirby about your content model

I’m hoping that caching the API and pages helps performance. Might also look into using the static site generator plugin. That would probably solve most performance issues.

How would you go about informing Kirby of the content model? At the moment, the only solution I can think of is checking if all the blueprint fields are to be saved through the panel manually, like in the example I posted above with “seoDescription”.