How to ignore subfolder

Hi everyone

I would like to know how to redirect my “projects” subfolder from

http://mydomain.com/projects/project-a

to

http://mydomain/project-a

I did some research but I don’t know how to do it. Maybe with htaccess file ?

Thx a lot

You can achieve that with a route, see the docs: https://getkirby.com/docs/developer-guide/advanced/routing#omitting-the-blog-folder-in-urls

Great, thanks a lot, but now, my sitemap.xml doesn’t work, why ?
I’m using the plugin from https://github.com/thgh/kirby-plugins/tree/master/sitemap

If I go to mydomain.com/sitemap.xml, I just see a blank page…:frowning:

Hm, the plugin uses another route, so these two interfere. I’m not sure how to best solve this. One way would be to change the route for the sitemap to sitemap/sitemap.xml in sitemap.php:

<?php
$exclude = c::get('sitemap.exclude', array('error'));
$important = c::get('sitemap.important', array('contact'));
kirby()->routes(array(
	array(
		'pattern' => 'sitemap/sitemap.xml',
		'action'  => function() use ($exclude, $important) {
			$sitemap = '<?xml version="1.0" encoding="utf-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
			foreach(site()->pages()->index() as $p){
				if(!in_array($p->uri(), $exclude)){
					$sitemap .= '<url><loc>' . html($p->url());
					$sitemap .= '</loc><lastmod>' . $p->modified('c') . '</lastmod><priority>';
					$sitemap .= ($p->isHomePage()||in_array($p->uri(), $important)) ? 1 : 0.6/$p->depth();
					$sitemap .= '</priority></url>';
				}
			}
			$sitemap .= '</urlset>';
			return new Response($sitemap, 'xml');
		}
	)
));

This is the code of my sitemap.xml

<?php

$exclude = c::get('sitemap.exclude', array('error'));
$important = c::get('sitemap.important', array('contact'));

kirby()->routes(array(
    array(
        'pattern' => 'sitemap.xml',
        'action'  => function() use ($exclude, $important) {

            $sitemap = '<?xml version="1.0" encoding="utf-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
            foreach(site()->pages()->index() as $p){
                if(!in_array($p->uri(), $exclude)){
                    $sitemap .= '<url><loc>' . html($p->url());
                    $sitemap .= '</loc><lastmod>' . $p->modified('c') . '</lastmod><priority>';
                    $sitemap .= ($p->isHomePage()||in_array($p->uri(), $important)) ? 1 : 0.6/$p->depth();
                    $sitemap .= '</priority></url>';
                }
            }
            $sitemap .= '</urlset>';

            return new Response($sitemap, 'xml');

        }
    )
));

As I stated above, if you change the pattern to

'pattern' => 'sitemap/sitemap.xml',

it should work.

Yes, sorry for my answer, your solution works fine !
So, I made my changes on my robots.txt like

sitemap: http://mydomain.com/sitemap/sitemap.xml

Thanks a lot and have a nice day.

Glad that it works now. Enjoy the day as well :slight_smile:

In case you want to keep the old sitemap URL: You could also handle that special case in your own route by checking if $uid is sitemap.xml.

That’s what I first thought as well, but could not get it to work. How exactly would you have to handle that case so as not to get into a endless loop?

Like that:

c::set('routes', array(
  array(
    'pattern' => '(:any)',
    'action'  => function($uid) {

      if($uid === 'sitemap.xml') {
        $sitemap = '<?xml version="1.0" encoding="utf-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
        foreach(site()->pages()->index() as $p){
          if(!in_array($p->uri(), c::get('sitemap.exclude', array('error')))){
            $sitemap .= '<url><loc>' . html($p->url());
            $sitemap .= '</loc><lastmod>' . $p->modified('c') . '</lastmod><priority>';
            $sitemap .= ($p->isHomePage()||in_array($p->uri(), c::get('sitemap.important', array('contact')))) ? 1 : 0.6/$p->depth();
            $sitemap .= '</priority></url>';
          }
        }
        $sitemap .= '</urlset>';
        
        return new Response($sitemap, 'xml');
      }

      $page = page($uid);

      if(!$page) $page = page('projects/' . $uid);
      if(!$page) $page = site()->errorPage();

      return site()->visit($page);

    }
  ),
  array(
    'pattern' => 'projects/(:any)',
    'action'  => function($uid) {
      go($uid);
    }
  )
));

Ah, ok, if you combine the two routes, yes.