How to define a virtual route for all blog articles?

I am in the last phase of moving my website from Ghost CMS to Kirby and on my old website all blog articles were listed directly on root level like web.site/blog-article. With Kirby I used the possibility to have a dedicated Blog page and now all my migrated blog articles can be found at web.site/de/blog/blog-article. Removing the language part (/de) of the URL is not a problem as it will be automatically added by Kirby but the additional “/blog” part of the URL is a problem for already existing blog articles as they cannot be found anymore using old links.
Is it possible to define a virtual route that adds the “/blog” part to the URL for every old blog article? Other parts of the website like web.site/en/about of course shouldn’t have this route.

Yes, this should work:

// other config settings
'routes' => [
  [
    'pattern'  => '(:any)',
    'language' => '*',
    'action'   => function($slug) {
      // try and find a first level page with the given slug
      if($page = page($slug)) {
        return $page;
      // otherwise, try to find the page in the blog folder and redirect
      } elseif($page = page('blog/' . $slug)){
        go($page);
      }
      // fall back to next route (alternatively, go directly to error page)
      $this->next();
    }
  ]
],

Thanks for the quick help but it doesn’t work. I used your code and fixed (?) two missing brackets like this:

      [
        'pattern'  => '(:any)',
        'language' => '*',
        'action'   => function($slug) {
          // try and find a first level page with the given slug
          if($page = page($slug)) {
            return $page;
          // otherwise, try to find the page in the blog folder and redirect
          } elseif($page = page('blog/' . $uid)) {
            go($page);
          }
          // fall back to next route (alternatively, go directly to error page)
          $this->next();
        }
      ]

Old website: Ressourcen der Erde verbraucht - Wo ist die nächste?
New website: https://dev.domain.de/de/blog/ressourcen-der-erde-verbraucht-wo-ist-die-nachste/

By using the code and trying to access https://dev.peleke.de/ressourcen-der-erde-verbraucht-wo-ist-die-nachste/ I just end up on the site not found error page.

Well, closing brackets manually is not my thing;)

There’s also a leftover wrong variable name, but try without the language:

   [
            'pattern'  => '(:any)',
            //'language' => '*',
            'action'   => function($slug) {
              // try and find a first level page with the given slug
              if($page = page($slug)) {
                return $page;
              // otherwise, try to find the page in the blog folder and redirect
              } elseif($page = page('blog/' . $slug)) {
                go($page);
              }
              // fall back to next route (alternatively, go directly to error page)
              $this->next();
            }
          ]

If you have other routes, make sure to use this first

Great, thanks!
Now it works as desired :slight_smile: