Route subdomains to specific content folders

Hi all!

I’m looking to convert my current Laravel, DB based website (basically a dictionary) to Kirby. I make use of wildcard domains and load content specific to each subdomain (something like birds.domain.com, cats.domain.com, dogs.domain.com etc). The structure is the same for every subdomain. In Laravel I use a middleware to check which subdomain is requested and load the content accordingly.

How would something like this work in Kirby? Ideally you’d have some kind of folder structure like content/cats/terms/whiskers/term.txt. Is this possible?

Come to think about it, this would affect the saving of files as well since everything needs to be saved into the appropriate folders.

Edit: it’s not the same as multisite (https://getkirby.com/docs/cookbook/setup/multisite)

Loading the content depending on the subdomain could be the same as in our multisite setup, but you could still have a main domain for the panel (maybe something like admin.domain.com) which would load all the content and pretend it’s all just one site.

Thanks for your quick reply!

Yeah, I’ve looked a bit more into multisite and it kind of resembles the setup, except that all domains share the same site folder, and not one per domain. But if that is what the setup should be like, then Kirby would not be an option because of the licensing. There’s currently 20+ content portals (as I call them) and that would mean 20+ licenses. Correct?

Edit: maybe I read too fast. I need to look into how to achieve what you’re referring to.

You need a license for every separate project or site. I.e. if you’d run a hosting platform similar to wordpress.com and every subdomain would be the site of another user (selma.superhosting.com, luise.superhosting.com, etc.) you’d need a separate license for every user.

If all your subdomains belong to a single project/site, you only need one license. Otherwise Kirby would be utterly useless for multi-language sites that prefer to have something like en.domain.com, de.domain.com instead of domain.com/en, domain.com/de

Understood. Reading up on how to get it working!

Am I heading in the right direction?

require __DIR__ . '/kirby/bootstrap.php';

$sites = [
    'cats.kirby.test' => 'cats',
    'dogs.kirby.test' => 'dogs',
  ];
  
  $host = Url::host();
  $root = $sites[$host];
  $url  = 'http://' . $host;

  $kirby = new Kirby([
    'roots' => [
      'index'   => __DIR__,
      'site'    => '/site',
      'content' => '/subjects/'. $root . '/content',
      'media'   => '/subjects/'. $root . '/media',
      'assets'  => '/subjects/'. $root . '/assets'
    ],
    'urls' => [
      'media'  => $url . '/subjects/'. $root . '/media',
      'assets' => $url . '/subjects/' . $root . '/assets',
    ],
  ]);
  
  echo $kirby->render();

I don’t think you need to modify the roots and urls of site, content, media and assets at all. Content should probably be enough.

Ah ok. Getting ‘This page is currently offline due to an unexpected error.’ (debug mode is on) but I’m pretty sure I can figure that out.

Thanks!

1 Like

Sorry, can’t seem to debug it. Could use some help. Currently I have this:

Note that I set some urls for api/current etc. I tried without setting those but that does not work either (see bottom of post).

require __DIR__ . '/kirby/bootstrap.php';

$domain = 'kirby.test';

$mainUrl = 'http://'. $domain;

$sites = [
    'cats.'. $domain => 'cats',
    'dogs.'. $domain => 'dogs',
  ];
  
$host = Url::host();
      
if ( ! isset($sites[$host])) {
    echo (new Kirby)->render();
} else {
    $root = $sites[$host];
    $url  = 'http://' . $host;
    
    $kirby = new Kirby([
        'roots' => [
            'index'   => __DIR__,
            'site'    => '/site',
            'content' => '/subjects/'. $root . '/content',
            'media'   => '/media',
            'assets'  => '/assets'
        ],
        'urls' => [
          'current'  => $mainUrl . '/panel',
          'api'  => $mainUrl . '/api',
          'panel'  => $mainUrl . '/panel',
          'media'  => $mainUrl . '/media',
          'assets' => $mainUrl . '/assets',
        ],
    ]);
    
    echo '<pre>';var_dump($kirby);echo '</pre>';die();
    
    echo $kirby->render();
}

That returns the following. Maybe you guys see something obvious that I might be missing:

object(Kirby\Cms\App)#6 (7) {
  ["languages"]=>
  object(Kirby\Cms\Languages)#197 (0) {
  }
  ["options"]=>
  array(0) {
  }
  ["request"]=>
  object(Kirby\Http\Request)#49 (5) {
    ["body"]=>
    object(Kirby\Http\Request\Body)#199 (0) {
    }
    ["files"]=>
    object(Kirby\Http\Request\Files)#200 (0) {
    }
    ["method"]=>
    string(3) "GET"
    ["query"]=>
    object(Kirby\Http\Request\Query)#201 (0) {
    }
    ["url"]=>
    string(23) "http://cats.kirby.test/"
  }
  ["roots"]=>
  object(Kirby\Cms\Ingredients)#37 (23) {
    ["kirby"]=>
    string(33) "/Users/gavin/Projects/kirby/kirby"
    ["i18n"]=>
    string(38) "/Users/gavin/Projects/kirby/kirby/i18n"
    ["i18n:translations"]=>
    string(51) "/Users/gavin/Projects/kirby/kirby/i18n/translations"
    ["i18n:rules"]=>
    string(44) "/Users/gavin/Projects/kirby/kirby/i18n/rules"
    ["index"]=>
    string(27) "/Users/gavin/Projects/kirby"
    ["assets"]=>
    string(7) "/assets"
    ["content"]=>
    string(22) "/subjects/cats/content"
    ["media"]=>
    string(6) "/media"
    ["panel"]=>
    string(39) "/Users/gavin/Projects/kirby/kirby/panel"
    ["site"]=>
    string(5) "/site"
    ["accounts"]=>
    string(14) "/site/accounts"
    ["blueprints"]=>
    string(16) "/site/blueprints"
    ["cache"]=>
    string(11) "/site/cache"
    ["collections"]=>
    string(17) "/site/collections"
    ["config"]=>
    string(12) "/site/config"
    ["controllers"]=>
    string(17) "/site/controllers"
    ["languages"]=>
    string(15) "/site/languages"
    ["models"]=>
    string(12) "/site/models"
    ["plugins"]=>
    string(13) "/site/plugins"
    ["sessions"]=>
    string(14) "/site/sessions"
    ["snippets"]=>
    string(14) "/site/snippets"
    ["templates"]=>
    string(15) "/site/templates"
    ["roles"]=>
    string(22) "/site/blueprints/users"
  }
  ["site"]=>
  object(Kirby\Cms\Site)#198 (8) {
    ["children"]=>
    object(Kirby\Cms\Pages)#206 (0) {
    }
    ["content"]=>
    object(Kirby\Cms\Content)#207 (0) {
    }
    ["errorPage"]=>
    bool(false)
    ["files"]=>
    object(Kirby\Cms\Files)#208 (0) {
    }
    ["homePage"]=>
    bool(false)
    ["page"]=>
    bool(false)
    ["title"]=>
    NULL
    ["url"]=>
    string(22) "http://cats.kirby.test"
  }
  ["urls"]=>
  object(Kirby\Cms\Ingredients)#39 (7) {
    ["index"]=>
    string(22) "http://cats.kirby.test"
    ["base"]=>
    string(22) "http://cats.kirby.test"
    ["current"]=>
    string(23) "http://kirby.test/panel"
    ["assets"]=>
    string(24) "http://kirby.test/assets"
    ["api"]=>
    string(21) "http://kirby.test/api"
    ["media"]=>
    string(23) "http://kirby.test/media"
    ["panel"]=>
    string(23) "http://kirby.test/panel"
  }
  ["version"]=>
  string(5) "3.4.2"
}

If I do not touch ‘urls’ at all it returns:

["urls"]=>
  object(Kirby\Cms\Ingredients)#35 (7) {
    ["index"]=>
    string(22) "http://cats.kirby.test"
    ["base"]=>
    string(22) "http://cats.kirby.test"
    ["current"]=>
    string(22) "http://cats.kirby.test"
    ["assets"]=>
    string(29) "http://cats.kirby.test/assets"
    ["api"]=>
    string(26) "http://cats.kirby.test/api"
    ["media"]=>
    string(28) "http://cats.kirby.test/media"
    ["panel"]=>
    string(28) "http://cats.kirby.test/panel"
  }

What does your folder setup look like?

image

(pixelijn, dat kan alleen maar een Nederlander zijn ;-))

Or someone in disguise :wink:

Ok, it seems that you only have different content folders, so most of your setup is not necessary, e.g. site, assets etc. do not need a setup in index.php, only the content folder. It’s a while since I tested this setup, so I will have to try it out later.

There is a difference:

In your screenshot, “media” is inside of your “$root”!
And I guess, this is ok!

Oh yeah, I see it :man_facepalming:t2:

But I’ve tried a few options and this is a leftover. It should not matter if there’s another media folder there though, just as long as you reference the correct one :slight_smile:

It works!!

But I’m a bit confused. I have this now:

$kirby = new Kirby([
        'roots' => [
            'content' => __DIR__. '/subjects/'. $root . '/content',
        ],
    ]);

Which seems to work. If I make the path relative, so just ‘/subjects/’. $root . ‘/content’, it doesn’t :thinking:

Is this the way to do it? (even though it works)

Yep, that looks good.

Good, but I think you need a second line there for the “media” in “roots” for every website too! They all need such an own directory like in your screenshot…

Note:
The path in the file system and in the shown “index.php” has for both dirs for every website (cats, …) to be the same.

1 Like