OpenGraph image generation when page is edited, not when image url is requested

Hi all,

I’ve followed this tutorial for generating OpenGraph images: Using content representations to create OG images | Kirby CMS

From my understanding, the image is re-generated at each call*. Would it be possible instead to have an image generation task be launched at every edit of a page, and have the image file stored in the page directory?

Thanks!

* the image re-generation for each call is especially problematic when you link your website on the Fediverse, where all instances getting your post make a call as they want to cache the image for their link previews… I’ve DDOS’d myself a couple of times that way

In the example, yes. I guess the article was published before Mastodon started becoming somewhat mainstream, and getting 3 or 4 requests wasn’t a problem.

This is how I would approach it if the generation actually causes performance issues:

site/config/config.php

<?php 

use Kirby\Cms\Page;

return [
    /** ... the usual stuff here */

    'hooks' => [
        'page.update:after' => function (Page $newPage) {
            // if the page has a createOgImage() method, call it.
            if(method_exists($newPage, 'createOgImage') {
                $newPage->createOgImage();
            }
        }
    ]
];

site/models/article.php

<?php 

use Kirby\Cms\Page;

class ArticlePage extends Page {

    /**
     * Generate the OpenGraph image
     */
    public function createOgImage() {
        $canvas = imagecreatetruecolor(1200, 628);

        // @TODO: draw stuff here

        // save file 
        imagepng($canvas, $this->root() . '/ogimage.png');

        // reset the internal cache so that kirby picks up the new file
        $this->purge();
    }

    /**
     * Generate the OpenGraph image if it doesn't exist
     * Return a File object for it
     */
    public function ogImage() {
        if($this->file('ogimage.png') === null)) {
            $this->createOgImage();
        }
        
        return $this->file('ogimage.png');
    }
}

in the template:

<meta
 property="og:image" 
 content="<?= $page->ogImage()?->url() ?? url('opengraph.png') ?>"
>

Docs:

1 Like

Thank you so much, your solution looks really perfect! I hadn’t thought of the hooks—I haven’t used them yet, it’s the perfect occasion :slight_smile: