Jack Baty

Director of Unspecified Services

Kirby routes and my URLs

One thing I wanted to make sure worked if moving the blog back to Kirby was URLs. In Kirby, by default this post would be listed at "/posts/2023/11/kirby-routes-and-my-urls" but I want it to be "/2023/11/kirby-routes-and-my-urls". Every other CMS I've used has made this relatively easy to do. In Kirby, it's... less easy.

I needed to add a couple of routes in Kirby's config.php, like so...

[
    // catch e.g. 2023/11/my-new-post-slug
    'pattern' => '(:num)/(:num)/(:any)',
    'action'  => function($year, $month, $slug) {
        $uid = $year . '/' . $month . '/' . $slug;
        $page = page($uid);
        if(!$page) $page = page('posts/'. $uid);
        if(!$page) $page = site()->errorPage();
        return site()->visit($page);
    }
],
[
    // catch the original url beginning with posts/
    'pattern' => 'posts/(:num)/(:num)/(:any)',
    'action'  => function($year, $month, $slug) {
        $uid = $year . '/' . $month . '/' . $slug;
        go($uid);
    }
]

This took me way too long to figure out. Between my own typos and of the examples assuming everything is in /blog/slug and not /YYYY/MM/slug, I lost some hair.

On the other hand, now that I'm beginning to understand it, I'll be able to do other fancy things later if needed.

The other thing that bugged me was that even though the routes properly handled links with /posts/... in them, I didn't want to see /posts/ anywhere. Turns out that's also doable by creating a custom model for posts and overriding the default url() method. I learned this after finding a forum post by Kev Quirk. I adapted it to suit my URL format in /site/models/post.php:

 public function url($options = null): string
    {
        return '/' . $this->date()->toDate('Y/m') . '/' . $this->slug();
    }

Now my URLs work the way I want them, so if I decide to move baty.net back to Kirby, I'm all set.

UPDATE: You're soaking in it.